Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

afterRender for html binding

Is there a way to run custom code after Knockout has added the html to the DOM and finished rendering? I need this so I can bind a nested view model to dynamically added html code.

Something like:

<div data-bind="html: dynamicHtml, afterRender: customCode"></div>

...

MyViewModel.prototype.customCode = function(){
    ko.applyBindings(self.MyInnerViewModel(), document.getElementById('someTagInTheDynamicHtml'));
};

afterRender is not called here (only works with template binding?), and a custom binding doesn't help either, because the "update" event is not guaranteed to be called after the DOM has been updated.

like image 373
seldary Avatar asked Apr 27 '13 09:04

seldary


1 Answers

Yes, afterRender works with template binding only.

But you can create custom binding handler that tracks html binding changes and fires callback when value is updated. My example:

ko.bindingHandlers.afterHtmlRender = {
    update: function(el, va, ab){
        ab().html && va()(ab().html);
    }
}

Shortened param names: va - valueAccessor, ab - allBindings.

Also the markup should look like that (binding name is changed):

<div data-bind="html: dynamicHtml, afterHtmlRender: customCode"></div>

http://jsfiddle.net/dDDjf/

Update

Simplified binding code with explanations:

ko.bindingHandlers.afterHtmlRender = {
    update: function(element, valueAccessor, allBindings){
        // check if element has 'html' binding
        if (!allBindings().html) return;
        // get bound callback (don't care about context, it's ready-to-use ref to function)
        var callback = valueAccessor();
        // fire callback with new value of an observable bound via 'html' binding
        callback(allBindings().html);
    }
}
like image 88
Rango Avatar answered Oct 19 '22 16:10

Rango