Reputation: 33388
I'm at the "hello world" stage with knockout.js and data-binding.
I can't find the right way to bind and update a member value of an object which is stored in an observableArray
.
Binding works first time, but then it doesn't update itself in the webpage.
Here's what i'm trying to do:
<div class="row" data-bind="foreach:chains">
<div class="col-md-12">
<h3>Obj id is <span data-bind="text: id"></span> </h3>
<span data-bind="text: message"></span>
</div>
</div>
javascript part:
(function () {
var Chain = function (chainId) {
var self = this;
self.id = chainId;
self.message = "N/A";
// etc. (more memberS)
};
var Model = function() {
var self = this;
self.chains = ko.observableArray();
};
Model.prototype = {
updateChains: function(updatedChains) {
// here chain values are updated, in words:
// if chain does not exist then create it and add it to self.chains
// self.chains.push(newChain);
// otherwise update chain.message as:
// existingChain.message = updatedMessage;
}
var model = new Model();
$(function() {
ko.applyBindings(model);
});
}());
I debugged the code and everything is fine on the update part, the message
gets a new value, but it's not visible in the UI (it remains "N/A"). It seems that i'm doing something wrong in the binding.
I tried several other ways but failed each time.
How can I achieve this?
Upvotes: 0
Views: 930
Reputation: 79461
From the Knockout page on Observable Arrays:
Key point: An
observableArray
tracks which objects are in the array, not the state of those objectsSimply putting an object into an
observableArray
doesn’t make all of that object’s properties themselves observable. Of course, you can make those properties observable if you wish, but that’s an independent choice. AnobservableArray
just tracks which objects it holds, and notifies listeners when objects are added or removed.
If you want the message
on a Chain
to be observable:
var Chain = function (chainId) {
var self = this;
self.id = chainId;
self.message = ko.observable("N/A");
...
};
Then, when you want to set the message
on an existing Chain
you need to do this:
existingChain.message(updatedMessage);
Not this:
existingChain.message = updatedMessage
Upvotes: 1
Reputation: 81
Observable arrays don't track their contents' state, only when the array itself is modified.
Documentation (second paragraph)
One way to achieve your goal would be to have the members of your Chain class also be observable:
var Chain = function (chainId) {
var self = this;
self.id = chainId;
self.message = ko.observable("N/A");
// etc. (more members)
};
Your update function would then be setting the observable in the found object:
self.chains()[foundIndex].memberToUpdate(newValue)
Upvotes: 1