Search code examples
javascriptjsonknockout-2.0knockout-mvc

Populating dropdownlist using knockout observable array


I am trying to bind 2 drop down lists to knockout observable arrays.The condition is that the first drop down list has to get populated first.The second drop down list is dependent on the first drop down list.Hence I am subscribing to the first drop down list to populate the second drop down list. To try and achieve this,I have written the following code

HTML is

       <div class="form-group">
            <label class="col-sm-2 control-label labelfont">Certification:</label>
            <div class="col-sm-6">
                <select class="form-control" id="certification" name="certification" data-bind="value: certification, options: certificationArray, optionsText: 'Certification', optionsValue: 'CertificationID', optionsCaption: 'Select a Certification'">
                </select>
            </div>
        </div>
    <div class="form-group">
             <label class="col-sm-2 control-label labelfont">Specialization:</label>
            <div class="col-sm-6">
                <select class="form-control" id="specialization" name="specialization" data-bind="value: specialization, options: specializationArray,optionsText:'Specialization',optionsValue:'SpecializationId', optionsCaption: 'Select a Specialization'">
                </select>
            </div>
        </div>

The view model is

   self.specializationArray = ko.observableArray([]);
   self.certificationArray = ko.observableArray([getCertifications()]);
   self.certification = ko.observable("");
   self.specialization = ko.observable("");
   self.certification.subscribe(function () {
    self.specializationArray([]);
    getSpecializations();    
    }
});

The functions to get the respective certifications and speciaizations are

 var getCertifications = function () {
$.getJSON("/Provider/GetCertifications", function (data) { 
    return data;
    });
});
};
    var getSpecializations = function () {
$.getJSON("/Provider/GetSpecializations/", { certificationID: $("#certification").val() }, function (data) {       
    self.specializationArray(data) 
   })
 }

The JSON response looks like this enter image description here and the JSON looks like this enter image description here Could someone please guide me in the right direction,I am completely new to knockout and JSON.I am at my wit's end here.So,any help would be greatly appreciated.Thanks in advance.


Solution

  • In KnockOut, the values of the arrays are separate from the options the dropdowns get. You wouldn't change the observableArray, but the value observable itself. Better, though, would be to use a ko.computed field to hold the value of the 2nd dropdown.

    I don't really understand why you think your dropdowns must get bound in a certain order, though. I'm not exactly sure how the Certifications and Specializations have to do with each other from your question. You aren't really doing anything in self.certification.subscribe(), like there was any dependency when filling in the Specialization. The JSON you supplied in the Certifications also does not have any related Specialization foreign key. But if your JSON for Certification looked like this:

    [{"CertificationID": 1, "Certification": "M.B.B.S.", "SpecializationID": "7"},{"CertificationID": 2, "Certification": "M.D.", "SpecializationID": "3"}, ...]
    

    while the JSON for Specialization looked like this...

    [{"SpecializationID": 1, "Specialization": "Cardiology"},
     {"SpecializationID": 2, "Specialization": "Dentistry"}, 
     {"SpecializationID": 3, "Specialization": "General Practioner"}, ...
     {"SpecializationID": 7, "Specialization": "Surgery"}
    ]
    

    I believe something like this should work:

    self.specialization = ko.computed(function() {        
        return ko.utils.arrayFirst(getCertifications(), function(certs) {
            return certs.ID == self.SpecializationID();
        }).SpecializationID;        
    });
    

    But since I don't see where you have any dependencies, here, why not just fill them in, directly:

    self.certificationArray = ko.observableArray(getCertifications());
    self.specializationArray = ko.observableArray(getSpecializations());
    self.certification = ko.observable(vm.certification);
    self.specialization = ko.observable(vm.specialization);
    

    And you set those values using the viewmodel returned from the dataset, which should be ID fields in your database table (CertificationID, SpecializationID).