1
votes

Currently having a problem with my Kendo grid's pagination/filtering. My grid is pretty standard, 6 columns, 4 that literally just spit out data from the model and 2 that display data from the model but have a Kendo tooltip applied with knockout bindings. The problem I'm having is specifically with the tooltip MVVM bindings. They work great with the first page of data but when you go to the second page, or filter the grid, the tooltips don't appear.

I've narrowed down the problem there, its that the new html for the new rows doesn't exist when the bindings are applied to the page. Simple problem of reapplying the bindings to the new html right? Wrong. Thats the solution I'm sure but I can't figure out how to accomplish it as its Kendo that is generating the new HTML and I can't figure out a way to intercept it and grab the new html to reapply the bindings to.

I'm assuming the solution would involve something like this:

self.interceptPaging = function(e) {
    var newElements = e.sender.content;
    ko.applyBindingsToNode(newElements[0], null, viewModel);
}

But where do I get the new elements from? As is, e.sender.content throws an error about binding the grid twice. Suggestions welcome!

See my Fiddle for a working example of my problem.

UPDATE:

As jsFiddle seems to be having problems working with knockout 3.2, I plugged this into Telerik's dojo: Here

UPDATE #2: SOLUTION

Found the solution. On top of the databound function above, I had to add a custom binding handler to disable descendant bindings.

ko.bindingHandlers.allowBindings = {
    init: function (elem, valueAccessor) {
        // Let bindings proceed as normal *only if* my value is false
        var shouldAllowBindings = ko.unwrap(valueAccessor());
        return { controlsDescendantBindings: !shouldAllowBindings };
    }
};

I added this attribute to the kendo grid div.

<div data-role="grid"
     data-bind="kendoGrid: gridOptions, allowBindings: false "
     style="height: 500px">
</div>

I also had to make a call to ko.cleanNode before the applyBindings call above. So my databound function looks like:

self.dataBound = function (e){
    var body = e.sender.element.find("tbody")[0];

    if (body) {
        ko.cleanNode(body);
        ko.applyBindings(ko.dataFor(body), body);
    }        
};

See updated Telerik Dojo.

1

1 Answers

1
votes

You are absolutely right. Kendo introduces new elements onto the page and knockout has no clue that it needs to apply bindings.

You can leverage the dataBound event for this:

dataBound: function(){
     var body = this.element.find("tbody")[0];

     if (body) {
        ko.applyBindings(ko.dataFor(body), body);   
     }}
}

I've updated your fiddle below.

http://jsfiddle.net/oe3nrk8f/2/

Also, take a look at this question to see how you could modify the source of the kendo-knockout library to do this for you automatically, but that might be overkill.

https://stackoverflow.com/a/13863191/4316646