I have an object:
{ model: settings: { "FirstName": "Joe", "LastName": "Bloggs" } };
in my view model I make settings an observable:
this.Settings = ko.observable(ko.mapping.fromJS(model.settings));
Which makes FirstName
and LastName
observables too.
In my view I bind by doing:
<p data-bind="text: Settings().FirstName"></p>
to read a value from Settings
I do:
`this.Settings().FirstName()`
The problem comes in when I want to subscribe when FirstName
OR LastName
changes.
I know I can do this.Settings.FirstName.subscribe...
but that's painful once you get more than two things you're observing.
Is there a way to do this.Settings.subscribe...
? or should I be using a custom binding?
I wrote the plugin below to help me deal with such situations:
https://github.com/ZiadJ/knockoutjs-reactor
Here's a simple usage example:
this.Settings.watch(function(root, trigger){
var newValue = trigger();
});
By using, computed observables, you can automatically update whenever any of these dependencies changes. For example, FullName will get updated when either Firstname or LastName changed.
this.Settings().FullName = ko.computed(function() {
return this.Settings().FirstName() + " " + this.Settings().LastName();
});
borrowed from KnokcoutJS.com
Note: I will work little more to make viewmodel little cleaner.
You should try the mapping plugin, which lets you take plain JSON objects and convert them to full view models.
Basically it converts every member on each object into an observable:
var data = { "FirstName": "Joe", "LastName": "Bloggs" };
var viewModel = ko.mapping.fromJS(data);
Then you could bind this viewmodel to your html a bind properties straightaway like this:
<p data-bind="text: FirstName"></p>
This is a small example, I only mapped a plain object, but you can also achieve more complex mappings if you wanted to convert nested objects like the one in your example. There is more information about this on the documentation.