I am using Knockout.js as a MVVM library to bind my data to some pages. I\'m currently building a library to make REST calls to a web service. My RESTful web service returns
I will extend Paolo del Mundo's answer (which I think it might easily be the best and the only solution at this moment) with my example solution.
Consider frapontillo's original object:
{
id : 1,
details: {
name: "Johnny",
surname: "Boy"
}
}
The details property itself is an object and as such CAN'T be an observable. The same goes for the User property in the example below, which is also an object. Those two objects cannot be observables but their LEAF properties can be.
Every leaf property of your data tree / model CAN BE AN OBSERVABLE. The easiest way to achieve that is that you properly define the mapping model before passing it to the mapping plugin as parameter.
See my example below.
EXAMPLE:
Let's say we need to show an html page / view where we have a list of users on a grid. Beside the Users grid a form for editing a selected user from the grid is shown.
STEP 1: DEFINING THE MODELS
function UsersEdit() {
this.User = new User(); // model for the selected user
this.ShowUsersGrid = ko.observable(false); // defines the grid's visibility (false by default)
this.ShowEditForm = ko.observable(false); // defines the selected user form's visibility (false by default)
this.AllGroups = []; // NOT AN OBSERVABLE - when editing a user in the user's form beside the grid a multiselect of all available GROUPS is shown (to place the user in one or multiple groups)
this.AllRoles = []; // NOT AN OBSERVABLE - when editing a user in the user's form beside the grid a multiselect of all available ROLES is shown (to assign the user one or multiple roles)
}
function User() {
this.Id = ko.observable();
this.Name = ko.observable();
this.Surname = ko.observable();
this.Username = ko.observable();
this.GroupIds = ko.observableArray(); // the ids of the GROUPS that this user belongs to
this.RoleIds = ko.observableArray(); // the ids of the ROLES that this user has
}
STEP 2: MAPPING (TO GET NESTED OBSERVABLES)
Let's say this is your raw JSON model with data that you want to map and get a KO model with nested observables.
var model = {
User: {
Id: 1,
Name: "Johnny",
Surname = "Boy",
Username = "JohhnyBoy",
GroupIds = [1, 3, 4],
RoleIds = [1, 2, 5]
}
};
Now that all of this is defined, you can map:
var observableUserEditModel = ko.mapping.fromJS(model, new UsersEdit());
AND YOU'RE DONE! :)
The observableUserEditModel will hold all of your observables, even nested ones. Now the only thing you need to take care of in order to test this is to bind the observableUserEditModel object with your HTML. Hint: use the with binding and test the observable observableUserEditModel data structure inserting this in your HTML view: