简体   繁体   中英

Cascading dropdown in knockout.js

I'm trying to populate another dropdownlist from a dropdown list, i keep getting error "TypeError: Unable to process binding "value: function (){return CompanySelected }" and " http://localhost/xxx/api/Transaction/LoadInsurancePolicies/undefined 400 (Bad Request)". Insurance Policy must be populated when Insurance company is chosen. this is the code below

  self.InsuranceCompanyId = ko.observable();
  self._companySelected= ko.observable(null);
  self.CompanySelected = ko.computed({
  read:  function () {return this._companySelected()  },
  write: function (value) {
  $.ajax({
         url: baseUrl + 'api/Transaction/LoadInsurancePolicies/' + 
         value.InsuranceCompanyId,
         type: 'GET',
         headers: { 'Access-Control-Allow-Origin': '*' },
         dataType: 'json',
         success: function (data) {
         if (data.Successfull == 1) 
         {
         self.AllPolicies(data.Model); } },
         error: function (request, error) {                
         }
        });

        this._companySelected(value);
    },
    owner: this     
    });
    self.AllInsuranceCompanies = ko.observableArray([]);
    self.AllPolicies = ko.observableArray([]);
    self.LoadInsuranceCompanies = function () {

    $.ajax({

        url: baseUrl + 'api/Transaction/LoadInsuranceCompanies',
        type: 'GET',
        headers: { 'Access-Control-Allow-Origin': '*' },
        dataType: 'json',
        success: function (data) {
            // console.log(data);
            if (data.Successfull == 1) {
                self.AllInsuranceCompanies(data.Model);
                console.log(data);
            }

        },
        error: function (request, error) {
            console.log(error);
        }
    });
  }
 self.LoadInsuranceCompanies();

 this is my view

  <div class="form-group" data-bind="visible:(InputOption()==0)">
  <label for="InputTxt" class="control-label col-md-4">Insurance 
  Company</label>
  <div class="col-md-8">
  <select data-bind="options: AllInsuranceCompanies,
                  optionsText: 'Name',
                  optionsValue:'Id',
                  optionsCaption: 'Choose...',
                  value:CompanySelected,
                  valueUpdate:'change'"  class="form-control">
                  </select>
                   </div>
                   </div>
  <div class="form-group" data-bind="visible: (InputOption()==0)">
  <label for="InputTxt" class="control-label col-md- 
  4">InsurancePolicy</label>
  <div class="col-md-8">
  <select data-bind="options: AllPolicies,
                    optionsText: 'Name',
                    optionsValue:'Id',
                    value: selectedPolicy,
                    optionsCaption: 'Choose...'" class="form-control"> 
 </select>
 </div>
 </div>

The following are probably the problems in your code.

  1. self.CompanySelected is defined before self.AllPolicies . This will cause to have a runtime error since ko.computed automatically runs when it is defined. This is based on knockout documentation. Solution: try defining all ko.observable before all ko.computed or atleast put self.AllPolicies before self.CompanySelected .
  2. Since the ko.computed automatically runs, and the value of self.CompanySelected is undefined , you will also have an undefined InsuranceCompanyId in your api call and this will result in Bad request 400. Solution: try adding a guard before calling your api. if(value){....}
  3. In your html bindings, you put optionsValue: 'Id' . This will result in knockout trying to find an Id property in your model which probably does not exist. Solution: remove optionsValue:'Id' from your bindings so that the value when changing option will be the model object itself and not just the Id .

Here is a sample fiddle: https://jsfiddle.net/przquhcf/1/ which implements the solutions above. Note: I just substituted setTimeout for your api calls since i dont have access to them. Dont worry about this part.

Your solution gave me an idea.I passed a function(value) and the value will be the selected Id,add it to the api as a parameter and it gets me the results.

self.insuranceCompanyId = ko.observable('');
self.selectedPolicy = ko.observable();  
self._companySelected = ko.observable();
self.CompanySelected = ko.pureComputed({
    read: function () {

        return this._companySelected()
    },

    write: function (value) {
        console.log("inside write", value)

        if (value) {
            console.log('data');
            $.ajax({

                url: baseUrl + "api/Transaction/LoadInsurancePolicies/" + 
                value,
                type: 'GET',
                headers: { 'Access-Control-Allow-Origin': '*' },
                dataType: 'json',
                success: function (data) {

                    if (data.Successfull == 1) {
                        self.AllPolicies(data.Model);
                        console.log(value);
                    }

                },
                error: function (request, error) {
                    console.log(error);
                }
            });
            this._companySelected(value);
        }

    },

    owner: this

});
self.LoadInsuranceCompanies();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM