Reputation: 2993
I have an issue whereby if I use a foreach binding with an observableArray, I am not seeing the changes made to the observableArray reflect on the screen.
The binding looks like this:
<div data-bind="foreach: items">
<p>
<input data-bind="value: name" />
</p>
<p>Name: <span data-bind="text: name"></span></p>
<br />
</div>
The observableArray looks like this:
this.items = ko.observableArray([
{ name: 'Person 1', role: 'Sales' },
{ name: 'Person 2', role: 'Accounts' },
{ name: 'Person 3', role: 'Admin' }
]);
Here is a JSFiddle to illustrate the problem: https://jsfiddle.net/ue3opdd2/2/
The HTML is split in 2 sections using a horizontal break. In section 1 is a binding which uses an observable. If you modify the text box, you see the change reflected in the span element below. This is working.
In section 2 is the exact same principal, but using an observableArray and a foreach binding. If you change the value in the "Person 1" text box for example, I would expect to see this change reflected in the span element below, but it doesn't work (it stays as "Name: Person 1").
I have put a debug output at the bottom of the screen and I do not see the values for the observableArray update in there either.
The main difference I can see is that the observableArray is a "complex type". By this I mean that each element is made up of an object containing a name and a role. Would this make a difference?
Can anyone help me to get this working please?
Upvotes: 2
Views: 899
Reputation:
observableArray
doesn't automatically make its contents observable:
Key point: An observableArray tracks which objects are in the array, not the state of those objects
Simply 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. An observableArray just tracks which objects it holds, and notifies listeners when objects are added or removed.
(From http://knockoutjs.com/documentation/observableArrays.html)
If you update your view model and make name
observable, your code should work the way you expect:
var ViewModel = function () {
this.item = ko.observable('Test name');
this.items = ko.observableArray([
{ name: ko.observable('Person 1'), role: 'Sales' },
{ name: ko.observable('Person 2'), role: 'Accounts' },
{ name: ko.observable('Person 3'), role: 'Admin' }
]);
};
ko.applyBindings(new ViewModel());
Upvotes: 4