Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

triggering beforeRemove, afterAdd handlers in KnockoutJS

Tags:

knockout.js

I am having some problems getting KnockoutJs beforeRemove and afterAdd handlers to fire.

This is the relevant code fragment

function viewModel(list) {
    var self = this;

    this.items = ko.observableArray(list);

    this.removeItem = function(item) {
        self.items.remove(item);
    }

    this.removeFirst = function() {
        self.removeItem(self.items()[0]);
    };

    this.onRemove = function(elements) {
        console.log("Updating");
        $(elements).addClass('transition-out');
    };
}

ko.applyBindings(new viewModel(items));

And this markup

<button data-bind="click: removeFirst">Remove first</button>
<ul data-bind='foreach: items, beforeRemove: onRemove'>
    <li data-bind="text: name, click: $parent.removeItem"></li>
</ul>

I am seeing list updates but the onRemove handler is never fired.

I've created a JSFiddle to illustrate the problem.

Thanks,

Gene

like image 822
Gene Golovchinsky Avatar asked Jan 12 '12 22:01

Gene Golovchinsky


People also ask

What is $data in knockout?

The $data variable is a built-in variable used to refer to the current object being bound. In the example this is the one of the elements in the viewModel.

For what purpose do we use foreach binding in Ko?

Purpose. The foreach binding duplicates a section of markup for each entry in an array, and binds each copy of that markup to the corresponding array item. This is especially useful for rendering lists or tables.

What is Ko dataFor?

ko. dataFor(element) - returns the data that was available for binding against the element. ko. contextFor(element) - returns the entire binding context that was available to the DOM element.

How do you bind data in an array?

If you want to access the array by index, you need to evaluate the observable first using () . If you want the value binding to work two-ways (i.e.: not only set it initially, but also update the values in your viewmodel after a change), you'll have to bind them to ko.


1 Answers

The syntax that you want to use looks like:

data-bind='foreach: { data: items, beforeRemove: onRemove }'

beforeRemove is an option that is accepted by the foreach (and ultimately the template) binding. It was being treated as a separate binding in the way that you were specifying it. If a binding does not exist, then it is ignored (some binding are accessed via allBindingsAccessor, so KO wouldn't know that and doesn't throw an error).

Also, the function will get called once for each node in your "template". In your case it will be a text node, the li, and another text node. If you want to ignore the text nodes, then check that the element's (first argument) nodeType is 1.

like image 51
RP Niemeyer Avatar answered Oct 05 '22 05:10

RP Niemeyer