Reputation: 760
I have this code in my javascript view model using Knockout. Everything works as designed, apart from I am struggling to get the two way binding update to work when the callback from my async call returns. See the code below.
var ViewModel = function (counterparty, scenario) {
this.counterparty = ko.observable(counterparty);
this.scenario = ko.observable(scenario);
this.choice = ko.computed(function () {
// Knockout tracks dependencies automatically.
//It knows that fullName depends on firstName and lastName,
//because these get called when evaluating fullName.
return this.counterparty() + " " + this.scenario();
}, this);
this.loginResult = ko.observable("");
// Do an asynchronous request to a rest service
var xmlhttp = new XMLHttpRequest();
var url = 'http://someloginurl';
xmlhttp.open('GET', url, true, 'user', 'pass');
xmlhttp.send(null);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var response = xmlhttp.responseXML;
this.loginResult = "Logged In To RNS Successfully";
} else {
// wait for the call to complete
}
};
this.availableCountries = ko.observableArray([
new Country("UK", 20000),
new Country("France", 30000)]);
this.selectedCountry = ko.observable();
};
var Country =
function(name, population) {
this.countryName = name;
this.countryPopulation = population;
};
ko.applyBindings(new ViewModel("", ""));
So I require this bit of code to update the binding showing the new value in the html for this.loginResult... But this is not happening and I am not sure why..
I thought that this line this.loginResult = ko.observable(""); should ensure that the value was a 'two-way binding' but it seems not.. Anyone know why this does not update?
The html tag for this is as follows:
<p><span data-bind="value: loginResult"> </span></p>
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var response = xmlhttp.responseXML;
this.loginResult = "Logged In To RNS Successfully";
} else {
// wait for the call to complete
}
Ok - I fixed this problem.. The solution is to refactor the code a little..
Firstly declare the variable upfront as an observable
// Do an asynchronous request to a rest service
this.loginResult = ko.observable('');
var url = 'someurl';
then refactor the method and pass in the variable so that its defined.
runAsyncRequest(url, this.loginResult);
function runAsyncRequest(url, loginResult) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', url, true, 'user', 'pass');
xmlhttp.send(null);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var response = xmlhttp.responseXML;
loginResult('Logged In To RNS Successfully');
} else {
// wait for the call to complete
}
};
}
All then works swimmingly and the binding is updated.
Upvotes: 0
Views: 1167
Reputation: 1670
To set a value in an observable, use
this.loginResult("Logged In To RNS Successfully");
Without the parenthesis, you are assigning a string variable to the loginResult, not filling it with data.
From the documentation on observables: (http://knockoutjs.com/documentation/observables.html)
To write a new value to the observable, call the observable and pass the new value as a parameter. For example, calling myViewModel.personName('Mary') will change the name value to 'Mary'.
Upvotes: 1