Thomas.Benz
Thomas.Benz

Reputation: 8599

'Delete' function works and does not work with ko.observableArray()

I am new to Knockout and still learn it.
I have a simple page so users can add and delete items. The 'delete' function (named 'deleteItem') works with Version 1 codes, but not with Version 2 codes. Please help me to know the reason behind. Thanks in advance.

By the way, the codes for Version 2 come from Note 7 near the bottom at the link http://knockoutjs.com/documentation/foreach-binding.html#note_5_postprocessing_or_animating_the_generated_dom_elements

The codes for Version 1 come from Example 2 at that same link.

Details of my codes:

The difference between the 2 versions is:

In Version 1, property 'myItems' is an array of objects that have 'name' property.
In Version 2, property 'myItems' is an array of elements that does not have any property. Those array elements are just literal strings.

Version 1 codes: the "Delete" function (named 'deleteItem') is working

<div>
    <ul data-bind="foreach: {data: myItems}">
        <li>
            <span data-bind="text: $data.name"></span> <a href="#"  data-bind="click : $parent.deleteItem" 

>Delete</a>
        </li>
    </ul>
    <button data-bind="click: addItem">Add</button>
</div

<script type="text/javascript">
    $(function () {
        function ViewModel() {
             var self = this;

            self.myItems = ko.observableArray([{ name: 'A' }, { name: 'B' }, { name: 'C' } ]);  /*********/
            self.addItem = function () { self.myItems.push({ name: 'New item at ' + new Date() }); }         


            self.deleteItem = function () {
                self.myItems.remove(this);
            };
        }

        ko.applyBindings(new ViewModel());

    });

</script>

Version 2: the "Delete" function (named 'deleteItem') is not working

<div>
    <ul data-bind="foreach: myItems">
        <li>
            <span data-bind="text: $data"></span> <a href="#"  data-bind="click : $parent.deleteItem" 

>Delete</a>
        </li>
    </ul>
    <button data-bind="click: addItem">Add</button>
</div>

<script type="text/javascript">
    $(function () {
        function ViewModel() {
            var self = this;

            self.myItems = ko.observableArray(['A', 'B', 'C']);  /*********/
            self.addItem = function () { self.myItems.push('item added at ' + new Date()); };

            self.deleteItem = function () {
                self.myItems.remove(this);
            };
        }

        ko.applyBindings(new ViewModel());

    });

</script>

Upvotes: 0

Views: 826

Answers (1)

nemesv
nemesv

Reputation: 139758

You should not expect the this to be the current model in a click handler.

Instead of the this you should use the fist parameter of the handler which is guaranteed to be the current model:

From the documentation:

When calling your handler, Knockout will supply the current model value as the first parameter.

So you need to rewrite your deleteItem to:

self.deleteItem = function (item) {
    self.myItems.remove(item);
};

Demo JSFiddle.

Note it will work in both of your samples.

Upvotes: 2

Related Questions