Populate dropdown based on previous selected value

When A user Selects A value in the location dropdown I want to populate the drop-down after it with certain values.
Add Screen: When User Selects A Location the Reference drop-down will be populated with one of two lists.


so if the user selects Substations the reference drop down should be populated with a list of substations, any other choice should populate the reference list with a list of trucks.



Here is what I have worked out so far. 
 var locationList = new Syncfusion.EJ2.DropDowns.DropDownList() { DataSource = @Model.Locations, Query = "new ej.data.Query()", AllowFiltering = true, Fields = new Syncfusion.EJ2.DropDowns.DropDownListFieldSettings() { Value = "LocationID", Text = "Description" } };

<ejs-grid id="Grid" dataBound="dataBound" height="510px" allowPaging="true" allowSorting="true" allowFiltering="true" allowGrouping="true" allowReordering="true" allowResizing="false" allowMultiSorting="true" allowPdfExport="true" allowExcelExport="true" showColumnChooser="true" toolbarClick="toolbarClick" printComplete='printComplete' actionComplete="actionComplete" actionBegin="actionBegin" toolbar="@(new List<string>() { "Add", "Edit","Print", "PdfExport", "ExcelExport", "Search","ColumnChooser" })">
        <e-grid-groupsettings></e-grid-groupsettings>
        <e-grid-filterSettings columns="filterColumns" type="Excel"></e-grid-filterSettings>
        <e-grid-pagesettings pageCount="6" pageSize="16" pageSizes="@(new string[] {"5", "10", "16", "20", "All"})"></e-grid-pagesettings>
        <e-grid-sortsettings columns="cols"></e-grid-sortsettings>
        <e-grid-editSettings allowAdding="true" allowEditing="true" mode="Dialog"></e-grid-editSettings>
        <e-data-manager json="@Model.Tools.ToArray()" adaptor="RemoteSaveAdaptor" insertUrl="/Home/AddTool" updateUrl="/Home/UpdateTool"></e-data-manager>
        <e-grid-columns>
            <e-grid-column field="LocationDescription" headerText="Location" width="120"></e-grid-column>
            <e-grid-column field="LocationID" headerText="Location" visible="false" editType="dropdownedit" edit="new {@params = locationList}"  width="50"></e-grid-column>
            <e-grid-column field="ReferenceID" headerText="Reference" visible="false" editType="dropdownedit" edit="@(new {create = "createReference", read = "readReference", destroy = "destroyReference", write = "writeReference"})" width="50"></e-grid-column>
           ...
        </e-grid-columns>
    </ejs-grid>

  var referenceElem;
    var referenceObject;
    var truckData = @Html.Raw(Json.Serialize(@Model.Trucks.ToArray()));
    var substationData = @Html.Raw(Json.Serialize(@Model.Substations.ToArray()));

    function createReference() {
        //  create a input element
        return document.createElement('input');
    }

    function readReference(args) {
        // return the value which will be saved in the grid
        return referenceObject.value;
    }

    function destroyReference() {
        // destroy the custom component.
        referenceObject.destroy();
    }

    function writeReference(args) {
        console.log(args);
        var locationId = args["rowData"]["LocationID"];
        var source = "";
        var description = "";
        var values = "";

        if (locationId === 2) {
            source = substationData;
            description = "name";
            values = "substationID";
        } else {
            source = truckData;
            description = "description";
            values = "truckID";
        }

        // create a dropdown control
        referenceObject = new ej.dropdowns.DropDownList({
            dataSource: source,
            placeholder: args.column.headerText,
            floatLabelType: "Always",
            value: args.rowData[args.column.field],
            fields: { text: description, value: values }
        });
        //render the component
        referenceObject.appendTo(args.element);
    }


7 Replies 1 reply marked as answer

SK Sujith Kumar Rajkumar Syncfusion Team April 26, 2021 11:08 AM UTC

Hi Danyelle, 
 
Greetings from Syncfusion support. 
 
Based on the query we could understand that your requirement is to render cascading dropdown list(provide a dropdown data source based on selected value from another dropdown) for Grid editing. This can be achieved using cell edit template feature on the dropdown columns and in the first dropdown’s change event, the second dropdown data can be modified(using query property) based on the selected value. 
 
This is demonstrated in the below sample code where the ShipCity dropdown data is modified based on the ShipCountry dropdown selected value in its change event, 
 
// “ShipCountry” dropdown cell edit template’s write method 
function CountryWrite() { 
   countryObj = new ej.dropdowns.DropDownList({ 
      dataSource: countryData, 
      fields: { value: 'countryId', text: 'countryName' }, 
      // “ShipCountry” dropdown’s change event handler 
      change: function () { 
        // The “ShipCity” edit dropdown is enabled(initially disabled using this property) 
        cityObj.enabled = true; 
        // A query is created based on the “ShipCountry’s” value so that only same value fields in the “ShipCity” dropdown is present in the data source 
        var tempQuery = new ej.data.Query().where('countryId', 'equal', countryObj.value); 
        // The created query is assigned to the “ShipCity” edit dropdown’s query property 
        cityObj.query = tempQuery; 
        cityObj.text = null; 
        cityObj.dataBind(); 
      }, 
      placeholder: 'Select a country', 
      floatLabelType: 'Never' 
  }); 
  countryObj.appendTo(countryElem); 
} 
 
We have prepared a sample for your reference. You can find it below, 
 
 
More details on rendering cascading dropdown lists in Grid edit can be checked in the below documentation link, 
 
 
Please get back to us if you require any further assistance. 
 
Regards, 
Sujith R 


Marked as answer

DA Danyelle April 26, 2021 02:31 PM UTC

What if I have two different lists? The location Id is not in these lists.

Location - LocationID
                  LocDescription

Substation - Substation ID
              SubDescription

Truck - Truck ID
             TruckDescription

So on the Change event it needs to be if  LocationID = 1 then set the temp query to the Substation list, If the LocationID = 2 set the temp query to the Truck list.




SK Sujith Kumar Rajkumar Syncfusion Team April 27, 2021 10:14 AM UTC

Hi Danyelle, 
 
Based on the query we could understand that you have two different lists(substation and truck) for the second dropdown and the dropdown data needs to be set based on the selected value from the first(location) dropdown. This can be achieved by directly changing the second dropdown data source instead of query based on the first dropdown’s selected value in its change event. 
 
This is demonstrated in the below code snippet, 
 
var USCityData = @Html.Raw(Json.Serialize(ViewBag.USCityData)); 
var AusCityData = @Html.Raw(Json.Serialize(ViewBag.AusCityData)); 
 
// “ShipCountry” dropdown cell edit template’s write method  
function CountryWrite() { 
    countryObj = new ej.dropdowns.DropDownList({ 
        dataSource: countryData, 
        fields: { value: 'countryId', text: 'countryName' }, 
        // “ShipCountry” dropdown’s change event handler  
        change: function () { 
            // The “ShipCity” edit dropdown is enabled(initially disabled using this property)  
            cityObj.enabled = true; 
            // The “ShipCity” edit dropdown data is assigned based on the current selected dropdown value  
            cityObj.dataSource = (countryObj.value === 1) ? USCityData : AusCityData; 
            // The edit dropdown data is refreshed  
            cityObj.dataBind(); 
        } 
    }); 
    countryObj.appendTo(countryElem); 
} 
 
We have modified the previously shared sample based on this for your reference. You can find it below, 
 
 
Let us know if you have any concerns. 
 
Regards, 
Sujith R 



DA Danyelle April 27, 2021 01:46 PM UTC

This is still not working. I think it has to do with the fact that my two lists have different names for value and text.
Substaion - SubstationID (value)
                   Name (text)

Location - LocationID (value)
                  description(text)

for this line in the writeReference method: 
 fields: { text: "description", value: "substationID" }

So for Substation it needs to be: 
fields: { text: "name", value: "substationID" }

For Truck It needs to be:
fields: { text: "description", value: "truckID" }

I tired this:
var locationValue;
function writeLocation(args) {

        // create a dropdown control
        locationObject = new ej.dropdowns.DropDownList({
            dataSource: locationData,
            placeholder: args.column.headerText,
            floatLabelType: "Always",
            fields: { text: "description", value: "locationID" },
            change: function () {
                referenceObject.enabled = true;
                referenceObject.dataSource = (locationObject.value === 2) ? substationData : truckData;
                referenceObject.dataBind();
                locationValue = (locationObject.value === 2) ? 2 : 1;
            }
        });
        //render the component
        locationObject.appendTo(args.element);


function writeReference(args) {

        var description = "";
        var values = "";

        if (locationValue === 1){
            description = "description";
            values = "truckID";
        }
        if (locationValue === 2) {
            description = "name";
            values = "substationID";
        }

        // create a dropdown control
        referenceObject = new ej.dropdowns.DropDownList({
            placeholder: args.column.headerText,
            floatLabelType: "Always",
            fields: { text: description, value: values },
            enabled: false
        });
        //render the component
        referenceObject.appendTo(args.element);
    }


But that does not appear to work. I am not getting any javascript errors. The Reference drop-down is showing blank.


When I step through the javascript it doesn't appear that it ever makes it to the writeReference method.



SK Sujith Kumar Rajkumar Syncfusion Team April 28, 2021 11:47 AM UTC

Hi Danyelle, 
 
From the provided code snippet we could see that you are trying to change the data source and field properties of the second dropdown based on the first dropdown selected value and you are performing this action in the second dropdown’s write method. We would like to let you know that the cell edit template’s write method(in your case – ‘writeLocation’, ‘writeReference’) will be triggered only when the controls are getting rendered initially(on dialog open) and it will not be triggered when changing dropdown values. 
 
So we suggest you to achieve your requirement by changing the second dropdown’s field property value also in the first dropdown’s change event. 
 
This is demonstrated in the below code snippet based on your scenario, 
 
function writeLocation(args) { 
    // create a dropdown control 
    locationObject = new ej.dropdowns.DropDownList({ 
        dataSource: locationData, 
        placeholder: args.column.headerText, 
        floatLabelType: "Always", 
        fields: { text: "description", value: "locationID" }, 
        change: function () { 
            referenceObject.enabled = true; 
            // The referenceObject dropdown’s data and fields are modified based on the locationObject dropdown selected value 
            if (locationObject.value === 2) { 
                referenceObject.dataSource = substationData; 
                referenceObject.fields = { value: 'substationID', text: 'name' }; 
            } else { 
                referenceObject.dataSource = truckData; 
                referenceObject.fields = { value: 'truckID', text: 'description' }; 
            } 
            referenceObject.dataBind(); 
        } 
    }); 
    //render the component 
    locationObject.appendTo(args.element); 
} 
 
We have modified the previously shared sample based on this query for your reference. You can find it below, 
 
 
Let us know if you have any concerns. 
 
Regards, 
Sujith R 



DA Danyelle April 28, 2021 03:28 PM UTC

Worked Great. Now I have a second question. I have a LocationDescription field that displays the location based on the location Id and Reference Id. I have got the field loading properly using valueAccessor but I need this property to be updated when I add/edit an item. Right now this property is not updated because the fields I am updating are the Location Id and Reference Id fields which is causing the row to not be displayed on the grid unless I refresh the entire page.

Code:
var locationAccessor = "locationAccessorFn";

//LocationID and ReferenceID are only shown on add/edit.  LocationDescription is only shown on the main grid.
 <ejs-grid id="Grid" dataBound="dataBound" height="510px" allowPaging="true" allowSorting="true" allowFiltering="true" allowGrouping="true" allowReordering="true" allowResizing="false" allowMultiSorting="true" allowPdfExport="true" allowExcelExport="true" showColumnChooser="true" toolbarClick="toolbarClick" printComplete='printComplete' actionComplete="actionComplete" actionBegin="actionBegin" toolbar="@(new List<string>() { "Add", "Edit","Print", "PdfExport", "ExcelExport", "Search","ColumnChooser" })">
        <e-grid-editSettings allowAdding="true" allowEditing="true" mode="Dialog"></e-grid-editSettings>
        <e-data-manager json="@Model.Tools.ToArray()" adaptor="RemoteSaveAdaptor" insertUrl="/Home/AddTool" updateUrl="/Home/UpdateTool"></e-data-manager>
        <e-grid-columns>
            <e-grid-column field="LocationDescription" headerText="Location" valueAccessor="locationAccessor" width="120"></e-grid-column>
            <e-grid-column field="LocationID" headerText="Location" visible="false" editType="dropdownedit" edit="@(new {create = "createLocation", read = "readLocation", destroy = "destroyLocation", write = "writeLocation"})"  width="50"></e-grid-column>
            <e-grid-column field="ReferenceID" headerText="Reference" visible="false" editType="dropdownedit" edit="@(new {create = "createReference", read = "readReference", destroy = "destroyReference", write = "writeReference"})" width="50"></e-grid-column>
...
        </e-grid-columns>
    </ejs-grid>

<script>

//This needs to happen when an item is added/edited so that the LocationDescription will be updated and the row will display in the grid.
  function locationAccessorFn(field, data, column) {
        var value = data[field];
        if (data["ReferenceID"] !== null) {
            if (data["LocationID"] === 2) {
                for (var i = 0; i < substationData.length; i++) {
                    if (data["ReferenceID"] === substationData[i].substationID) {
                        value = substationData[i].name;
                    } 
                }
                
            }
            if (data["LocationID"] === 1) {
                value = data["Location"]["Description"] + " "  + data["ReferenceID"];
            }
        }

        return value;
    }


 var locationValue;
    var locationElem;
    var locationObject;
    var locationData = @Html.Raw(Json.Serialize(@Model.Locations.ToArray()));
    var referenceElem;
    var referenceObject;
    var truckData = @Html.Raw(Json.Serialize(@Model.Trucks.ToArray()));
    var substationData = @Html.Raw(Json.Serialize(@Model.Substations.ToArray()));

//Create/read/destroy not shown

  function writeLocation(args) {

        // create a dropdown control
        locationObject = new ej.dropdowns.DropDownList({
            dataSource: locationData,
            placeholder: args.column.headerText,
            floatLabelType: "Always",
            fields: { text: "description", value: "locationID" },
            change: function () {
                referenceObject.enabled = true;
                if (locationObject.value === 2) { 
                    referenceObject.dataSource = substationData; 
                    referenceObject.fields = { value: 'substationID', text: 'name' }; 
                } else { 
                    referenceObject.dataSource = truckData; 
                    referenceObject.fields = { value: 'truckID', text: 'description' }; 
                } 

                referenceObject.dataBind();
                
            }
        });
        //render the component
        locationObject.appendTo(args.element);
    }

 function writeReference(args) {

        // create a dropdown control
        referenceObject = new ej.dropdowns.DropDownList({
            placeholder: args.column.headerText,
            floatLabelType: "Always",
            enabled: false
        });
        //render the component
        referenceObject.appendTo(args.element);
    }


SK Sujith Kumar Rajkumar Syncfusion Team April 29, 2021 10:37 AM UTC

Hi Danyelle, 
 
We are glad to hear that the provided solution worked for you. As for this query – “I have got the field loading properly using valueAccessor but I need this property to be updated when I add/edit an item”, we would like to let you know that on performing save action(both add and edit), the value accessor function will be triggered(from where you can return the updated value) automatically and it was working fine on checking from our end. You can check the below modified sample and video demo for reference, 
 
 
 
We suspect that the condition might not be properly executed in the value accessor function of your application causing the reported problem. So we suggest you to ensure if the proper value is returned from the value accessor function by debugging this case on save. If it is properly returned but problem still persists then please share us the following information to validate further on this, 
 
  • Video demonstration of the problem to understand it better.
  • Syncfusion package version used.
  • Share us the server side code used in your application for handling CRUD actions for remote save adaptor.
  • Please let us know if you are able to reproduce your problem case in the above shared sample. Or else if possible share us a simple sample to replicate the problem.
 
Regards, 
Sujith R 


Loader.
Up arrow icon