Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

knockoutjs afterRender function in foreach binding

I'm trying to specify an entrance effect on elements being inserted using a knockoutjs foreach binding. Very simple setup:

myViewModel.myObservableArray.push({enter:function() { ... });

and in the markup:

foreach:{data:myObservableArray, afterRender:enter}

seems like it should work... right? But it doesn't find the enter function on the item. What I've found does work is:

myViewModel.enter = function(something, item) { item.enter(); };

foreach:{data:myObservableArray, afterRender:$root.enter}

adding an enter function to the root view model and binding afterRender to $root.enter. Enter is then passed the item as its second param so can in turn call the item's enter function, but it feels like a hack.

Can anyone explain what's going on here?

Thanks.

EDIT:

To clarify I've created a fiddle.

What this does is very simple, and is covered in more depth in the animated transitions example. It's running a function in the root view model for each dom element that's inserted using the foreach binding.

So the question is: what if I want item specific afterRender, afterAdd or beforeRemove functions? I could see this being useful. Especially if using the template binding to dynamically select a template (note 4). Is there a clean way of doing this? Right now I've got an enter function in the view model's root that simply calls the enter function on the item, but like I said above this feels like a hack.

like image 915
nicholas Avatar asked Jul 31 '12 21:07

nicholas


People also ask

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 are the types of binding supported by knockout JS?

Binding Values The binding value can be a single value, literal, a variable or can be a JavaScript expression.

What is $root in knockout?

$root. This is the main view model object in the root context, i.e., the topmost parent context. It's usually the object that was passed to ko. applyBindings . It is equivalent to $parents[$parents.

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.


1 Answers

Nope, this is the way it was designed.

From the Documenation:

Note 3: Using “afterRender”, “afterAdd”, and “beforeRemove”

Sometimes you might want to run custom post-processing logic on the DOM elements generated by your templates. For example, if you’re using a JavaScript widgets library such as jQuery UI, you might want to intercept your templates’ output so that you can run jQuery UI commands on it to transform some of the rendered elements into date pickers, sliders, or anything else.

Generally, the best way to perform such post-processing on DOM elements is to write a custom binding, but if you really just want to access the raw DOM elements emitted by a template, you can use afterRender.

Pass a function reference (either a function literal, or give the name of a function on your view model), and Knockout will invoke it immediately after rendering or re-rendering your template.

(Emphasis mine)


As it says, a custom binding is another way to do it, and may be better depending on what that enter() function does.

like image 71
Kyeotic Avatar answered Sep 20 '22 20:09

Kyeotic