Question

I have an HTML page in an Asp.Net MVC 4 application in which I have several dropdown lists to deal with. In one case I am trying to populate a dropdown list with results based on the value selected in the first dropdown box.

For Example, I have an SQL table with following structure

Id    ProductName   GradeName
1       Petroleum      A
2       Petroleum      B
3       Petroleum      C
4       Grains         1
5       Grains         2
6       Grains         3

So, when I select Petroleum in Product List then my Grade list should be populated with A,B,C

Knockout Js and Odata

var GradeViewModel = function () {

     $.ajax({
            dataType: "json",
            url: '/odata/Grades',
            data: ko.toJSON(self.grades),
            async: false,
            success: function (data) {
                self.gradeNames((ko.utils.arrayMap(data.value, function (grade) {
                    var obsGrade = {
                        Id: grade.Id,
                        ProductName: ko.observable(grade.ProductName),
                        GradeName: ko.observable(grade.GradeName),
                        Edit: ko.observable(false),

                        Locked: ko.observable(grade.Locked)
                    }
                    self.watchModel(obsGrade, self.modelChanged);
                    return obsGrade;
                })));
            }
        });



}

 GradeViewModel.filteredItems = ko.computed(function () {
            var filter = GradeViewModel.selectedChoice();

            if (!filter) {
                return GradeViewModel.gradeNames();
            } else {

                var filtered = ko.utils.arrayFilter(GradeViewModel.gradeNames(), function (item) {
                    return (item.ProductName() === filter);
                });

                return filtered
            }
        })

      var viewModel = new GradeViewModel();
     ko.applyBindings(viewModel);

HTML

<td>

 <select data-bind="options: $root.gradeNames, optionsText: 'ProductName', optionsValue: 'ProductName', value: selectedChoice, optionsCaption: 'Product'">
  </select>
 </td>

 <td>   
 <select data-bind="options: $root.gradeNames, optionsText: 'GradeName', optionsValue: 'GradeName', enable:selectedChoice, value: selectedGrade, optionsCaption: 'Grade'">
 </select>
 </td>

May I know a good way to do it.

Was it helpful?

Solution

Considering you already have the relevant data, no need in querying via a subscription. So for this particular case, I would use one of the available utility methods.

  • ko.utils.arrayFilter

    viewModel.filteredItems = ko.computed(function () {
      var filter = viewModel.selectedChoice();
    
      if (!filter) { 
       return viewModel.gradeNames();
      } else {
    
        var filtered = ko.utils.arrayFilter(viewModel.gradeNames(), function (item) {
          return (item.ProductName() === filter);
        });
    
        return filtered;
      } 
    })
    

The html for the GradeName select would then become

 <select data-bind="options: $root.filteredItems, optionsText: 'GradeName', optionsValue: 'GradeName', enable:selectedChoice, value: selectedGrade, optionsCaption: 'Grade'">

Reference this example.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top