.net MVC, C#, KnockoutJS
So I have 2 dropdowns. Both whose data is being populated via Ajax call from knockout to MVC controller function. The initial setup works fine where on selection of first dropdown the second dropdown populates. What I need to do is pass the text and value selected from the second dropdown on the button click event to the next controller. I have tried both subscribe and onchange but cant get the value and text selected from the second dropdpown. Here is the code below:
Dropdown 1
<select data-bind="options: countries ,
optionsText: 'Name',
optionsValue: 'ID',
value: selectedCountry,
optionsCaption: '--Please Select--'" asp-placeholder-for="Country" asp-for="Country" class="form-control common-input-text"></select>
Dropdown 2
<select data-bind="options: states ,
optionsText: 'Name',
visible: ifSelected,
optionsValue: 'ID',
event: { change: selectionChanged },
value: selectedState"
asp-placeholder-for="State" asp-for="State"
class="form-control common-input-text"></select>
Knockout
(function () {
var viewModel = function (vmData) {
var self = this;
self.countries = ko.observableArray();
self.selectedCountry = ko.observable();
self.states = ko.observableArray();
self.ifSelected = ko.observable(false);
self.selectedState = ko.observable();
//Populate Country DDL
$.ajax({
url: rootDir + "/Home/GetCountry",
type: "GET",
contentType: "application/json",
async: false,
success: function (data) {
self.countries(JSON.parse(data));
}
});
//Populate state DDL based on country
self.selectedCountry.subscribe(function (val) {
$.ajax({
url: rootDir + "/Home/GetStates",
type: "GET",
data: { stateVal: val },
contentType: "application/json",
async: false,
success: function (data) {
var jsonData = JSON.parse(data);
self.ifSelected(true);
self.states(jsonData);
}
});
});
//I have tried to subscribe to second dropdown but this function is never hit
self.selectedState.subscribe(function (value) {
});
//I have tried to bind onchange event to state dropdown but the selected value is always null
self.selectionChanged = function(event) {
var a = self.selectedState(); //null or udefined
}
};
var pageVM = new viewModel();
ko.applyBindings(pageVM, $("form")[0]);
})();
The code you've posted seems fine. "selectedState" holds the ID of the item that was selected. If you want the whole object instead of just the ID consider removing the "optionsValue: 'ID'" binding from the states dropdown.
var viewModel = function(vmData) {
var self = this;
self.countries = ko.observableArray();
self.selectedCountry = ko.observable();
self.states = ko.observableArray();
self.ifSelected = ko.observable(false);
self.selectedState = ko.observable();
//Populate Country DDL
setTimeout(function(data) {
self.countries([{ Name: 'us', ID: 1 }, { Name: 'ca', ID: 2 }, { Name: 'mx', ID: 3 }]);
}, 500);
//Populate state DDL based on country
self.selectedCountry.subscribe(function(val) {
console.log('country changed');
setTimeout(function(data) {
self.ifSelected(true);
self.states([{ Name: 'ca', ID: 1 }, { Name: 'nv', ID: 2 }, { Name: 'tx', ID: 3 }]);
}, 500);
});
//I have tried to subscribe to second dropdown but this function is never hit
self.selectedState.subscribe(function(value) {
console.log('state changed');
});
//I have tried to bind onchange event to state dropdown but the selected value is always null
self.selectionChanged = function(event) {
var a = self.selectedState(); //null or udefined
}
};
var pageVM = new viewModel();
ko.applyBindings(pageVM);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="options: countries ,
optionsText: 'Name',
optionsValue: 'ID',
value: selectedCountry,
optionsCaption: '--Please Select--'" asp-placeholder-for="Country" asp-for="Country" class="form-control common-input-text"></select>
<select data-bind="options: states ,
optionsText: 'Name',
visible: ifSelected,
event: { change: selectionChanged },
value: selectedState" asp-placeholder-for="State" asp-for="State" class="form-control common-input-text"></select>
<br/>
selectedState: <span data-bind="text: ko.toJSON(selectedState)"></span>