Took me a few minutes to remember how to do this the right way, which is to update your bindings from inside the AJAX success callback function.
The problem is the disconnect between the call to FromDb() and the AJAX success function. Returning the value from the success function happens asynchronously, meaning there is no way for the code to know to hook the value returned back into the MaptoKo(new FromDb()) call. When you make the FromDb() call just return { name: 'test' };, that's happening synchronously, so the result does make it into the MaptoKo function.
$.getJSON("/some/url", function(data) {
// Now use this data to update your view models,
// and Knockout will update your UI automatically
})
So, all Knockout needs to help you do is: ...
- For loading, update your view model using data that you’ve received using one of the above techniques
Source: Knockout JSON Data Docs
For your specific code, that would mean something like the following:
function FriendsViewModel() {
var self = this;
self.friends = ko.observable();
// Load the initial data
$.ajax({
type: 'GET',
url: 'http://rest.learncode.academy/api/johnbob/friends',
//dataType: "json",
success: function(data) {
//returns all of johnbob's friends
console.log("I have friends!", data[0]);
myResult = data[0];
// Don't return the result, bind it to the viewmodel
self.friends(myResult);
}
});
}
ko.applyBindings(new FriendsViewModel());
This is well covered in the Loading and Saving tutorial. Note that this no longer really makes use of the mapping plugin. To tie that in, following the advice of the mapping plugin docs:
To create a view model via the mapping plugin, replace the creation of viewModel in the code above with the ko.mapping.fromJS function:
var viewModel = ko.mapping.fromJS(data);
This automatically creates observable properties for each of the properties on data. Then, every time you receive new data from the server, you can update all the properties on viewModel in one step by calling the ko.mapping.fromJS function again:
// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);
$.(function (){
// Load the initial data
$.ajax({
type: 'GET',
url: 'http://rest.learncode.academy/api/johnbob/friends',
//dataType: "json",
success: function(data) {
//returns all of johnbob's friends
console.log("I have friends!", data[0]);
myResult = data[0];
// Don't return the result, bind it to the viewmodel
var viewModel = ko.mapping.fromJS(myResult);
// Only bind once after the initial load.
// If you save or reload data, don't reapply bindings
ko.applyBindings(viewModel);
}
});
});
That last example is just a guess, I've never used the mapping plugin myself. But hopefully it illustrates that you can't just return results from async callbacks.