Reputation: 13
The knockout website has a great example of adding and removing list items using a foreach binding, but how would you update these values? I've tried doing so in the following fiddle, but the DOM elements do not respond to my update: http://jsfiddle.net/SC5Lw/1/
<ul data-bind="foreach: people">
<li>
Name at position <span data-bind="text: $index"> </span>:
<span data-bind="text: name"> </span>
<a href="#" data-bind="click: $parent.removePerson">Remove</a>
<a href="#" data-bind="click: $parent.updatePerson">Update</a>
</li>
</ul>
var person1 = ko.observable({ name: 'Bert' });
var person2 = ko.observable({ name: 'Charles' });
var person3 = ko.observable({ name: 'Denise' });
self.people = ko.observableArray([person1, person2, person3]);
...
self.updatePerson = function(person) {
for(var i = 0 ; i < self.people.length ; i++)
{
if(self.people[i].name === person.name)
{
self.people[i].name = 'Bob';
}
}
};
I've made the elements of the observableArray into observables themselves, so I'm not sure why the elements they are bound to don't react to changing the property in the view model.
Upvotes: 1
Views: 7768
Reputation: 45135
What you need to do is create a class for people with a ko.observable
called name
. That's not what you've done here. You've made person1
and observable, but it contains an object literal with a normal property called name
.
Something like this:
function Person(name) {
var self = this;
self.name = ko.observable(name);
}
Now in your parent VM:
var person1 = new Person('Bert');
var person2 = new Person('Charles');
var person3 = new Person('Denise');
self.people = ko.observableArray([person1, person2, person3]);
Here's a working fiddle.
Also, I wouldn't bother with your loop to find the matching person
. You already have the person, so just change it's property right there.
So instead of this (which doesn't work anyway because people
is a function, not a property):
self.updatePerson = function(person) {
for(var i = 0 ; i < self.people.length ; i++)
{
if(self.people[i].name === person.name)
{
self.people[i].name = 'Bob';
}
}
};
You can just do:
self.updatePerson = function(person) {
person.name("Bob");
}
You could even make this cleaner by moving this function to your Person
view model and doing it there:
function Person(name) {
var self = this;
self.name = ko.observable(name);
self.updateMe = function() {
self.name("Bob");
}
}
Which avoids having to bind $parent
in your foreach
loop:
<a href="#" data-bind="click: updateMe">Update</a>
Here's a fiddle with those updates too.
Upvotes: 2