Reputation: 2535
I have the following select:
<select data-bind=" options: states,
optionsText: 'acronym',
optionValue: 'stateId',
value: state">
</select>
ViewModel and dependencies:
function State(state) {
var self = this;
self.stateId = ko.observable(state.StateId);
self.acronym = ko.observable(state.Acronym);
}
function AddressViewModel() {
var self = this;
self.cities = ko.observableArray([]);
self.states = ko.observableArray([]);
self.zipcode = ko.observable();
self.city = ko.observable();
self.state = ko.observable();
self.stateHard = ko.observable();
self.address = ko.observable();
self.addressNumber = ko.observable();
self.address2 = ko.observable();
self.town = ko.observable();
self.phoneNumber = ko.observable();
self.mobileNumber = ko.observable();
self.state.subscribe(function () {
self.UpdateCities();
});
self.UpdateCities = function () {
if (self.state())
$.getJSON("/api/v1/address/cities/" + self.state().stateId(),
function (data) {
self.cities($.map(data, function (item) {
return new City(item) }));
});
}
$.getJSON("/api/v1/user/address/", function (data) {
self.zipcode(data.zipcode);
self.city(new City(data.city));
self.state(new State(data.state));
self.address(data.address);
self.addressNumber(data.addressNumber);
self.address2(data.address2);
self.town(data.town);
self.phoneNumber(data.phoneNumber);
self.mobileNumber(data.mobileNumber);
$.getJSON("/api/v1/address/states", function (data) {
self.states($.map(data, function (item) {
return new State(item) }));
});
});
}
But when I involke ko.applyBindings(new AddressViewModel());
the AVM.state
loses its original value, although that value is in the list.
I already tried to invert the getJSON
order (states before state and vice versa) but nothing new happened.
Upvotes: 0
Views: 137
Reputation: 1502
There's actually a few issues going on here.
optionsValue
value wrong in your data-bind section.optionsValue
option correctly, when you choose an item from the drop-down, you will be writing State.stateId
to AVM.state
; however in your initialisation call you create an object: self.state(new State(data.state))
. You can't expect that to work; you're initialising with an object reference but updating with a literal value.If you spelled the optionsValue
option incorrectly and would like to keep it working this way - first up delete optionValue
so you don't get confused. Next - be aware that an object will be written to AVM.state
. The object equivalence testing is done by reference, not by deep-inspection of the objects values. You would need to pull a reference from AVM.states
and write it to AVM.state
. Something like this:
// Use the data.state.StateId to find the correct state from the states list.
self.state(ko.utils.arrayFirst(self.states(), function (s) {
return s.stateId() === data.state.StateId;
}));
The order of initialisation is important IF the databinding occurs before you've finished all your AJAX calls. If databinding occurs before all ajax calls are complete the following is the sequence of events:
ko.applyBindings(AVM);
is called, options: binds against the empty AVM.states
list.AVM.state
is set.AVM.state
is not in AVM.states
and writes NULL to AVM.state
.AVM.states
is set.AVM.states
to update the dropdown with options, and by default the first one is selected.I've attached references to a couple JSFiddles showing two approaches to the problem.
Version 1 - Using optionsValue
in the data-bind call:
http://jsfiddle.net/Lam42/1/
Version 2 - Removing optionsValue
and using object references:
http://jsfiddle.net/sFW4j/
Upvotes: 2
Reputation: 169
You have to create a function and move the code block $.getJSON("/api/v1/user/address/",.. inside the function. And then, call that function after invoking ko.applyBindings(new AddressViewModel());.
Upvotes: 0