- Home
- Forum
- React - EJ 2
- Cascading DropDownList with backing id field
Cascading DropDownList with backing id field
Hi.
I looked at the example for a cascading dropdown list:
https://ej2.syncfusion.com/react/documentation/grid/how-to/cascading-drop-down-list-with-grid-editing/
and tried to implement it with backing fields. I couldn't really get it to work. Here an example of my attempt:
It shows the ids instead of customer name or location name. Somehow the dropdown list doesn't seem to be connected to the content. What am I doing wrong or is there a working example for this somewhere?
Thanks
Alexander
SIGN IN To post a reply.
15 Replies
1 reply marked as answer
AG
Ajith Govarthan
Syncfusion Team
January 20, 2021 12:28 PM UTC
Hi Alexander,
Thanks for contacting Syncfusion support.
Query: It shows the ids instead of customer name or location name. Somehow the dropdown list doesn't seem to be connected to the content. What am I doing wrong or is there a working example for this somewhere?
Based on the attached sample we found that you have used the foreignkey column and edit template in your grid application. Before we proceed to your query, we need to confirm the below details to provide you the prompt solution the earliest.
- Please let us know you want to show the customerName and the locationName in grid columns with foreign key column feature or you want to show the customerName and the locationName while perform the editing and updating the record.
- Share the screenshot or video demonstration of your requirement to understand clearly about your requirement.
Regards,
Ajith G.
AE
Alexander Esser
January 22, 2021 07:53 AM UTC
Hi.
In view mode it should show customerName and locationName. When editing a row it should show dropdown lists for Customer and Location where the underlying customerId and locationid are mapped correctly.
Ideally the grid datasource should only contain the customerId and locationId and the mapping is done in the Customer and Location columns.
Hope that makes sense
Best
Alexander
AE
Alexander Esser
January 22, 2021 08:30 AM UTC
Here a screenshot:
(https://1drv.ms/u/s!Appi7cLK7BVzjv5_ohdvazYTGqylZw?e=d3QtvB)
AG
Ajith Govarthan
Syncfusion Team
January 25, 2021 12:13 PM UTC
Hi Alexander,
Thanks for the update.
Query: Query: It shows the ids instead of customer name or location name. Somehow the dropdown list doesn't seem to be connected to the content. What am I doing wrong or is there a working example for this somewhere?
We have checked attached sample and in that sample we found that you have used the foreignkey column but you have not defined the dataSource for the foreignkey columns. By default, when you are not defined the datasource for the column then the columns will show only the grid dataSource values instead of foreignkey values.
So, we suggest you use the dataSource for the columns to apply the foreignkey values properly based on the foreignkeyField and foreignkeyValue. For your convenience we have attached the sample and the documentation so please refer them for your reference.
Code Example:
|
Index.js
export class ForeignKeyColumn extends SampleBase {
constructor() {
super(...arguments);
this.toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
this.validationRules = { required: true };
}
render() {
return (<div className='control-pane'>
<div className='control-section'>
<GridComponent dataSource={orderDetails} allowPaging={true} ref={grid => this.gridInstance = grid} allowFiltering={true} allowSorting={true} editSettings={{ allowEditing: true, allowDeleting: true, allowAdding: true }} filterSettings={{ type: 'Menu' }} toolbar={this.toolbarOptions}>
<ColumnsDirective>
<ColumnDirective field='OrderID' headerText='Order ID' width='120' textAlign='Right' validationRules={this.validationRules} isPrimaryKey={true}></ColumnDirective>
<ColumnDirective field='CustomerID' headerText='Customer Name' width='150' validationRules={this.validationRules} foreignKeyValue='ContactName' foreignKeyField='CustomerID' dataSource={customerData}></ColumnDirective>
<ColumnDirective field='Freight' headerText='Freight' width='100' format='C2' textAlign='Right' editType='numericedit'/>
<ColumnDirective field='ShipName' headerText='Ship Name' width='170'></ColumnDirective>
<ColumnDirective field='ShipCountry' headerText='Ship Country' width='150' editType='dropdownedit'></ColumnDirective>
</ColumnsDirective>
<Inject services={[Filter, Page, Edit, Sort, ForeignKey, Toolbar]}/>
</GridComponent>
</div>
</div>);
}
}
render(<ForeignKeyColumn />, document.getElementById('sample')); |
Please get back to us if you need further assistance.
Regards,
Ajith G.
AE
Alexander Esser
January 25, 2021 12:49 PM UTC
Hi.
Thank you for your example, but it doesn't exactly fit my problem. I'm interested in a cascading dropdown list example. In the example I had added (https://codesandbox.io/s/determined-haibt-rl4iz) the location depends on the customer. When I try setting the datasource of the dropdown fields the component doesn't start at all. (I assume the challenge is somewhere in using the EditCell elements and the foreign key setup).
My example is based on another example on your help pages (https://ej2.syncfusion.com/react/documentation/grid/how-to/cascading-drop-down-list-with-grid-editing/), but that example doesn't use underlying ids to connect the data grid source with the dropdown fields; it uses the text for mapping those. So I would need a short description why my example isn't working or another example the shows the correct implementation of cascading dropdown lists using underlying id values.
Please let me know if I was able to describe my problem.
Thanks
Alexander
AG
Ajith Govarthan
Syncfusion Team
January 29, 2021 01:43 AM UTC
Hi Alexander,
Sorry for the delayed update.
Query: I'm interested in a cascading dropdown list example. In the example I had added (https://codesandbox.io/s/determined-haibt-rl4iz) the location depends on the customer. When I try setting the datasource of the dropdown fields the component doesn't start at all. (I assume the challenge is somewhere in using the EditCell elements and the foreign key setup).
Based on your attached sample you want to have cascading dropdown with foreignkey columns. So, based on that we have prepared sample and in that sample we have defined two foreignkey columns and also used the editTemplate feature to achieve cascading dropdown.
We have also used text values to map to the dropdown dataSource as per your requirement. For your convenience we have attached the sample so please refer them for your reference.
Code Example:
|
Index.js
import { render } from "react-dom";
import "./index.css";
import { DataManager, Query } from "@syncfusion/ej2-data";
import * as React from "react";
import { DropDownList } from "@syncfusion/ej2-dropdowns";
import {
GridComponent,
ColumnsDirective,
ColumnDirective,
Page,
Filter,
Inject,
Edit,
Sort,
ForeignKey,
Toolbar
} from "@syncfusion/ej2-react-grids";
import { orderDetails, customerData } from "./data";
import { SampleBase } from "./sample-base";
export class ForeignKeyColumn extends SampleBase {
constructor() {
super(...arguments);
this.toolbarOptions = ["Add", "Edit", "Delete", "Update", "Cancel"];
this.countryElem;
this.countryObj;
this.stateElem;
this.stateObj;
this.validationRules = { required: true };
this.country = [
{ ContactName: "Paul Henriot", CustomerID: "VINET", id: "1" },
{ ContactName: "Karin Josephs", CustomerID: "TOMSP", id: "2" },
{ ContactName: "Mario Pontes", CustomerID: "HANAR", id: "3" },
{ ContactName: "Mary Saveley", CustomerID: "VICTE", id: "4" },
{ ContactName: "Pascale Cartrain", CustomerID: "SUPRD", id: "5" },
{ ContactName: "Yang Wang", CustomerID: "CHOPS", id: "6" }
];
this.stateColl = [
{
CompanyName: "Alfreds Futterkiste",
CustomerID: "VINET",
countryId: "1",
stateId: "101",
Country: "Germany"
},
{
CompanyName: "Ana Trujillo Emparedados y helados",
CustomerID: "TOMSP",
stateId: "102",
Country: "Mexico"
},
{
CompanyName: "Antonio Moreno",
CustomerID: "VINET",
stateId: "103",
Country: "Mexico"
},
{
CompanyName: "Around the Horn",
CustomerID: "HANAR",
stateId: "104",
Country: "UK"
},
{
CompanyName: "Berglunds snabbköp",
CustomerID: "SUPRD",
stateId: "105",
Country: "Sweden"
},
{
CompanyName: "Blauer See Delikatessen",
CustomerID: "CHOPS",
stateId: "106",
Country: "Germany"
},
{
CompanyName: "Blondesddsl père et fils",
CustomerID: "SUPRD",
stateId: "105",
Country: "France"
},
{
CompanyName: "Bólido Comidas preparadas",
CustomerID: "HANAR",
stateId: "106",
Country: "Spain"
},
{
CompanyName: "Blauer See Delikatessen",
CustomerID: "VICTE",
stateId: "106",
Country: "Germany"
}
];
this.countryParams = {
create: () => {
this.countryElem = document.createElement("input");
return this.countryElem;
},
destroy: () => {
this.countryObj.destroy();
},
read: () => {
return this.countryObj.value;
},
write: () => {
this.countryObj = new DropDownList({
change: () => {
this.stateObj.enabled = true;
const tempQuery = new Query().where(
"CustomerID",
"equal",
this.countryObj.value
);
this.stateObj.query = tempQuery; // in the change event of the first dropdown generate query for second dropdown.
this.stateObj.text = "";
this.stateObj.dataBind();
},
dataSource: new DataManager(this.country),
fields: { value: "CustomerID", text: "ContactName" },
floatLabelType: "Never",
placeholder: "Select a country"
});
this.countryObj.appendTo(this.countryElem);
}
};
this.stateParams = {
create: () => {
this.stateElem = document.createElement("input");
return this.stateElem;
},
destroy: () => {
this.stateObj.destroy();
},
read: () => {
return this.stateObj.value;
},
write: () => {
this.stateObj = new DropDownList({
dataSource: new DataManager(this.stateColl),
enabled: false,
fields: { value: "Country", text: "CompanyName" },
floatLabelType: "Never",
placeholder: "Select a state"
});
this.stateObj.appendTo(this.stateElem);
}
};
}
render() {
return (
<div className="control-pane">
<div className="control-section">
<GridComponent
dataSource={orderDetails.slice(0, 8)}
allowPaging={true}
ref={grid => (this.gridInstance = grid)}
allowFiltering={true}
allowSorting={true}
editSettings={{
allowEditing: true,
allowDeleting: true,
allowAdding: true
}}
filterSettings={{ type: "Menu" }}
toolbar={this.toolbarOptions}
>
<ColumnsDirective>
<ColumnDirective
field="OrderID"
headerText="Order ID"
width="120"
textAlign="Right"
validationRules={this.validationRules}
isPrimaryKey={true}
/>
<ColumnDirective
field="CustomerID"
headerText="Customer Name"
width="150"
validationRules={this.validationRules}
foreignKeyValue="ContactName"
foreignKeyField="CustomerID"
dataSource={customerData}
edit={this.countryParams}
/>
<ColumnDirective
field="Country"
headerText="Company Name"
foreignKeyValue="CompanyName"
foreignKeyField="Country"
dataSource={customerData}
edit={this.stateParams}
width="170"
/>
<ColumnDirective
field="Freight"
headerText="Freight"
width="100"
format="C2"
textAlign="Right"
editType="numericedit"
/>
<ColumnDirective
field="ShipCountry"
headerText="Ship Country"
width="150"
editType="dropdownedit"
/>
</ColumnsDirective>
<Inject
services={[Filter, Page, Edit, Sort, ForeignKey, Toolbar]}
/>
</GridComponent>
</div>
</div>
);
}
}
render(<ForeignKeyColumn />, document.getElementById("sample")); |
Please get back to us if you need further assistance.
Regards,
Ajith G.
Marked as answer
AE
Alexander Esser
February 1, 2021 08:05 AM UTC
Hi and thank for the example. I tried to implement something similar using TypeScript. When I set the the datasource attribute on the column tag the grid won't show any data and only show a spinner in front of the grid. What can be reason for that?
AG
Ajith Govarthan
Syncfusion Team
February 2, 2021 12:19 PM UTC
Hi Alexander,
Thanks for the update.
Query: I tried to implement something similar using TypeScript. When I set the the datasource attribute on the column tag the grid won't show any data and only show a spinner in front of the grid. What can be reason for that?
Based on your query you are facing grid rendering issue when setting the dataSource property in the column. We have checked our given sample and found everything works fine.
To find the root cause of the issue, please share the below details to provide the prompt solution at the earliest.
1. If possible, please try to reproduce the issue in the attached sample.
2. Share the complete grid code example.
3. Share the screenshot or video demonstration of your requirement.
4. Please let us know if you have used remote data or local data in your grid application.
5. Share the Syncfusion package version.
Regards,
Ajith G.
AE
Alexander Esser
February 2, 2021 01:36 PM UTC
Hi Ajith.
I looked at the JS example you provided and that seems to work. I was referring to the TypeScript example I created a while ago (https://codesandbox.io/s/determined-haibt-rl4iz?file=/src/demoGrid.tsx) and simplified now based on your example. When I remove the comment for the dataSource attribute in line 220:
<ColumnDirective
field="customerId"
headerText="Customer"
width="150"
validationRules={this.validationRules}
foreignKeyValue="customerName"
foreignKeyField="customerId"
//dataSource={CustomerLocations}
edit={this.customerParams}
/>
the grid won't show any data and just a spinner in front of an empty grid. What could be the reason for this?
There might also be other issues since the customerId is shown and not the name, but that might fall into place when the basics start to work.
Best
Alexander
YK
yogita Kashyap
February 3, 2021 07:02 AM UTC
I was also facing similar type issues in my code. Anyways glad that i could join your discussion. I was able to find the solution for my problem here itself. Thank You both
RS
Rajapandiyan Settu
Syncfusion Team
February 3, 2021 11:41 AM UTC
Hi Alexander,
Thanks for your update.
We have validated the provided sample at our end. We found that the foreignKey service is not injected in the Grid.
Grid component features are segregated into individual feature-wise modules. In order to use a particular feature, you need to inject its feature service in the App. Refer to the below documentation for more information.
We suggested you to inject the ForeignKey service in the Grid to resolve the reported problem.
|
[demoGrid.tsx]
<GridComponent
dataSource={GridData}
----
>
-----
<Inject services={[Edit,ForeignKey, Toolbar]} />
</GridComponent> |
Please get back to us if you need further assistance with this.
Regards,
Rajapandiyan S
AE
Alexander Esser
February 4, 2021 08:30 AM UTC
Hi Rajapandiyan.
That was my bad. I hadn't seen that it had fallen out in the list.
There were also some naming issues in my example that I fixed now. It starts looking better, but saving changes doesn't seem to work. Instead of the id the respective name in the drop down is used. You can see the update result in the Console window in the bottom right, e.g.:
{"id":"id1","info":"Demo 1","customerId":"Cust Two","customerName":"Cust One","locationId":"Loc Two B","locationName":"Loc Two B"}
What could the reason for this.
Alex
AG
Ajith Govarthan
Syncfusion Team
February 5, 2021 02:04 PM UTC
Hi Alexander,
Thanks for your update.
Query: There were also some naming issues in my example that I fixed now. It starts looking better, but saving changes doesn't seem to work. Instead of the id the respective name in the drop down is used. You can see the update result in the Console window in the bottom right
Based on your query you are facing update issue with dropdown component. So, we have checked your attached sample and found that you have returned the text of the dropdown component instead of value.
So, we suggest you return the value property of the dropdown instead of text in the read method. We have also found that you have not used the dataSource property for the location column. So, please ensure the mentioned changes to avoid the issue.
For your convenience we have attached the sample so please refer the sample for your reference.
Code Example:
|
DemoGrid.tsx
import React from "react";
import _ from "lodash";
import "@syncfusion/ej2-base/styles/material.css";
import "@syncfusion/ej2-buttons/styles/material.css";
import "@syncfusion/ej2-calendars/styles/material.css";
import "@syncfusion/ej2-dropdowns/styles/material.css";
import "@syncfusion/ej2-inputs/styles/material.css";
import "@syncfusion/ej2-navigations/styles/material.css";
import "@syncfusion/ej2-popups/styles/material.css";
import "@syncfusion/ej2-splitbuttons/styles/material.css";
import "@syncfusion/ej2-react-grids/styles/material.css";
import { DropDownList } from "@syncfusion/ej2-dropdowns";
import { DataManager, Query } from "@syncfusion/ej2-data";
import {
GridComponent,
ColumnsDirective,
ColumnDirective,
EditSettingsModel,
PageSettingsModel,
ActionEventArgs,
GroupEventArgs,
FilterEventArgs,
SearchEventArgs,
SortEventArgs,
AddEventArgs,
SaveEventArgs,
EditEventArgs,
PageEventArgs,
DeleteEventArgs
} from "@syncfusion/ej2-react-grids";
import {
Edit,
ForeignKey,
IEditCell,
Inject,
Page,
Toolbar,
ToolbarItems
} from "@syncfusion/ej2-react-grids";
import {
Customers,
CustomerLocations,
GridData,
ICustomer,
IGridData,
ICustomerLocation
} from "./gridData";
type SyncfusionAction =
| PageEventArgs
| GroupEventArgs
| FilterEventArgs
| SearchEventArgs
| SortEventArgs
| AddEventArgs
| SaveEventArgs
| EditEventArgs
| DeleteEventArgs
| ActionEventArgs
| undefined;
interface IDemoGridProps {}
interface IDemoGridState {
dataSourceGrid: IGridData[] | undefined;
loading: boolean;
}
export default class DemoGrid extends React.Component<
IDemoGridProps,
IDemoGridState
> {
constructor(props: IDemoGridProps) {
super(props);
this.state = {
dataSourceGrid: undefined,
loading: true
};
this.gridInstance = React.createRef<GridComponent>();
this.customerElem = undefined;
this.customerObj = undefined;
this.locationElem = undefined;
this.locationObj = undefined;
}
private customerElem: HTMLElement | undefined;
private customerObj: DropDownList | undefined;
private locationElem: HTMLElement | undefined;
private locationObj: DropDownList | undefined;
private customersDm = new DataManager([]);
private locationsDm = new DataManager([]);
private gridInstance: React.RefObject<GridComponent>;
private toolbarOptions: ToolbarItems[] = ["Add", "Edit", "Update", "Cancel"];
private editSettings: EditSettingsModel = {
allowEditing: true,
allowAdding: true,
allowDeleting: true,
newRowPosition: "Top",
mode: "Normal"
};
private pageSettings: PageSettingsModel = { pageCount: 5 };
private validationRules = { required: true };
public async componentDidMount(): Promise<void> {
_.each(Customers, (cust: ICustomer) => this.customersDm.insert(cust));
_.each(CustomerLocations, (cl: ICustomerLocation) =>
this.locationsDm.insert(cl)
);
this.setState({ dataSourceGrid: GridData, loading: false });
}
public customerParams: IEditCell = {
create: () => {
this.customerElem = document.createElement("input");
return this.customerElem;
},
destroy: () => {
if (!!this.customerObj) this.customerObj.destroy();
},
read: () => {
return !!this.customerObj ? this.customerObj.value : "";
},
write: () => {
this.customerObj = new DropDownList({
change: () => {
if (!!this.customerObj && !!this.locationObj) {
this.locationObj.enabled = true;
const tempQuery: Query = new Query().where(
"customerId",
"equal",
this.customerObj.value
);
this.locationObj.query = tempQuery;
this.locationObj.text = "";
this.locationObj.dataBind();
}
},
dataSource: this.customersDm,
fields: { value: "customerId", text: "customerName" },
floatLabelType: "Never",
placeholder: "Select a customer"
});
this.customerObj.appendTo(this.customerElem);
}
};
public locationParams: IEditCell = {
create: () => {
this.locationElem = document.createElement("input");
return this.locationElem;
},
destroy: () => {
if (!!this.locationObj) this.locationObj.destroy();
},
read: () => {
return !!this.locationObj ? this.locationObj.value : "";
},
write: () => {
debugger;
this.locationObj = new DropDownList({
dataSource: this.locationsDm,
enabled: false,
fields: { value: "locationId", text: "locationName" },
floatLabelType: "Never",
placeholder: "Select a location or leave empty"
});
this.locationObj.appendTo(this.locationElem);
}
};
private actionComplete = (args: SyncfusionAction): void => {
const captains = console;
captains.log(!!args ? args.requestType : "Unknown request type");
const actionEvent = args as ActionEventArgs;
const data = actionEvent?.data;
captains.log(JSON.stringify(data));
};
public render() {
return this.state.loading ? (
<div>Loading ...</div>
) : (
<div>
<h3>The Grid:</h3>
<GridComponent
dataSource={GridData}
ref={this.gridInstance}
toolbar={this.toolbarOptions}
allowPaging={true}
editSettings={this.editSettings}
pageSettings={this.pageSettings}
actionComplete={this.actionComplete}
title="Grid Test"
>
<ColumnsDirective>
<ColumnDirective
field="id"
headerText="Id"
width="100"
isPrimaryKey={true}
visible={true}
/>
<ColumnDirective
field="info"
headerText="Info"
width="250"
textAlign="Left"
validationRules={this.validationRules}
/>
<ColumnDirective
field="customerId"
headerText="Customer"
width="150"
validationRules={this.validationRules}
foreignKeyValue="customerName"
foreignKeyField="customerId"
dataSource={this.customersDm}
edit={this.customerParams}
/>
<ColumnDirective
field="locationId"
headerText="Location"
width="150"
type="string"
foreignKeyField="locationId"
foreignKeyValue="locationName"
dataSource={this.locationsDm}
edit={this.locationParams}
/>
</ColumnsDirective>
<Inject services={[Edit, ForeignKey, Page, Toolbar]} />
</GridComponent>
</div>
);
}
} |
Sample Link: https://codesandbox.io/s/confident-wildflower-pjdzb
Please get back to us if you need further assistance.
Regards,
Ajith G
AE
Alexander Esser
February 5, 2021 02:26 PM UTC
Hi Ajith.
That was the missing piece I hadn't noticed.
Thanks for clarifying
Alexander
RR
Rajapandi Ravi
Syncfusion Team
February 9, 2021 09:42 AM UTC
Hi Alexander,
We are happy to hear that your issue has been resolved.
Please get back to us if you need further assistance.
Regards,
Rajapandi R
SIGN IN To post a reply.
- 15 Replies
- 5 Participants
- Marked answer
-
AE Alexander Esser
- Jan 19, 2021 03:26 PM UTC
- Feb 9, 2021 09:42 AM UTC