Let's say I have the following code:
var Klass = function(){
var self = this;
this.value = 123;
this.update = function(){
$.ajax({
url: '/whatever',
async: false,
success: function(data){
$.extend(self, data);
}
});
}
}
Lets assume, '/whatever' returns this json object:
{value: 234}
And when I do this:
var obj = new Klass();
obj = ko.mapping.fromJS(obj);
console.log(obj);
We all know obj
is now an knockoutjs observable.
And I run this:
obj.update();
console.log(obj);
What I have discovered is, value of obj
doesn't get overridden as a simple value 234, but stayed as an observable property.
My questions are:
1) why is this?
2) How do I make the update work as I wanted.
UPDATE: ajax call is not asynchronous.
First issue is that you are extending self
, which is a scoped variable and only exists inside the Klass function, not it's instances you create by calling it.
You'll need to call $.extend(this, data);
if you need to overwrite value
when calling update
.
Although I do understand why you are using self
there.
But the observable
functionality added by calling ko.mapping.fromJS
is then lost. value
is no longer a function (ko observable
) but a scalar value (234
). You have to call obj = ko.mapping.fromJS(obj);
again to wrap value as observable
.
Second issue is that $.get
is asynchronous so calling console.log(obj)
right after calling obj.update
will log the value before the GET response comes. You need to wait for it to execute (use a callback).
Here's a working fiddle.
var Klass = function(){
this.value = 123;
this.update = function(callback){
var self = this;
$.get('/', function(data) {
$.extend(self, {value: 234});
callback.call(undefined);
});
}
}
var obj = new Klass();
obj = ko.mapping.fromJS(obj);
console.log(obj.value());
obj.update(function() {
obj = ko.mapping.fromJS(obj);
console.log(obj.value());
});