Reputation: 1482
Hey I am trying to remove a item from a inner(nested) observableArray as following, but the Remove Button doesn't work (for the inner foreach items).
http://jsfiddle.net/aDahT/1871/
html:
<h4>People</h4>
<ul data-bind="foreach: peoples">
<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>
<ul data-bind="foreach:people">
<li>
<span data-bind="text: $data"></span>
<button data-bind="click: $parent.deletePerson">Remove</button>
</li>
</ul>
</li>
</ul>
<button data-bind="click: addPerson">Add</button>
Script:
var Person = function(name, children){
var self = this;
self.name = name;
self.people = ko.observableArray(children);
self.deletePerson = function() {
alert(JSON.stringify(self));
self.people.remove(this);
}
}
function AppViewModel() {
var self = this;
self.peoples = ko.observableArray([
new Person( 'Bert', ['baa', 'bbb'] ),
new Person('Charles', ["caa", "cbb"] )
]);
self.addPerson = function() {
alert(this);
self.peoples.push(new Person( "New" ,["Daa", "Dbb"] ));
}.bind(this);
self.removePerson = function() {
self.peoples.remove(this);
}
}
ko.applyBindings(new AppViewModel());
Can anyone help? Thanks first.
Upvotes: 2
Views: 1334
Reputation: 7641
You can try also (jsfiddle):
<ul data-bind="foreach:people">
<li>
<span data-bind="text: name"></span>
<button data-bind="click: function() {$parent.people.remove($data)}, text: 'remove ' + name"></button>
</li>
</ul>
var model = {
people: ko.observableArray([{ name: "a"}, { name: "b"}, { name: "c"}])
};
ko.applyBindings(model);
Upvotes: 0
Reputation: 139758
Just use the first parameter of your click handler which is always set to the current view model:
self.deletePerson = function(viewModel) {
self.people.remove(viewModel);
}
Demo JSFiddle.
Knockout also sets the this
to the current viewmodel in your handlers but there is a big difference in your deletePerson
and the removePerson
.
In the removePerson
the this
is an object (your Person
object) but in your deletePerson
the this should be a primitive type: a string.
However Knockout uses apply
to call your function and it boxes primitive types: JavaScript function call/apply with string
You check this if you log out this
to the console. You will see something like:
String {0: "c", 1: "a", 2: "a", length: 3, [[PrimitiveValue]]: "caa"}
So you will end up a boxed string in your deletePerson
in the this
and you need to use valueOf()
(or the toString()
) to get its value:
self.deletePerson = function() {
self.people.remove(this.valueOf());
}
So just always use the first parameter provided by KO which is always the original value.
Upvotes: 2