Cause Knockout to re-draw data columns based on changes to my column model when using tempate nodes binding
Asked Answered
N

1

0

My problem scenario is almost identical to this one but the table I'm drawing has TD cells with more complex bindings, each binding unique to the column being bound. Sometimes it's just the HTML that's unique.

In other words, it isn't good enough to loop the columns using a databind=foreach and simply nest a <TD> that does a text binding.

I can get my table to render on initial page draw, using a template{nodes:xxx} binding, where I pass in an array of DOM nodes.. like this:

    <table>
        <thead>
            <tr>
              <!-- ko foreach: ColumnModel.VisibleColumns -->
                <th data-bind="click:$root.ColumnModel.ColumnSortClick,text:ColName"></th>
              <!-- /ko -->
            </tr>
        </thead>
        <tbody>
            <!-- ko template: { nodes: ColumnModel.getRowTmplNodes(), foreach: DataItems} -->
            <!-- /ko -->
        </tbody>
    </table>

The documentation states that the DOM nodes you pass to this variable are not allowed to be an observableArray. So, as you can imagine, when I allow the users to update the column model, only my header labels change in the <THEAD>, but the data columns do not update.

What do I do?

Nectarine answered 18/9, 2017 at 15:19 Comment(2)
Ok, I found a way to make this work, and switched from using the template binding to a custom binding handler thanks to Michael BestNectarine
You can post that as an answer and accept it.Grandeur
N
1

Solved by using a custom knockout binding described originally here by Michael Best

HTML:

<table>
    <thead>
       <tr>
        <!-- ko foreach: ColumnModel.VisibleColumns -->
          <th data-bind="click:$root.ColumnModel.Column_Click" style="cursor:pointer;"><span data-bind="visible:SortDirection,css:IconClass" style="font-size:small"></span><span data-bind="text:ColName"></span></th>
        <!-- /ko -->
       </tr>
    </thead>
    <tbody data-bind="foreach:{data:DataItems,as:'thg'}">
       <tr data-bind="nodes: $root.ColumnModel.getRowTemplate()"></tr>                
    </tbody>
</table>

KO BINDING:

//THANK YOU, MICHAEL BEST:
ko.bindingHandlers.nodes = {
    init: function () {
    return {controlsDescendantBindings: true};
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    var nodes = ko.unwrap(valueAccessor());
    ko.virtualElements.setDomNodeChildren(element, nodes);
    ko.applyBindingsToDescendants(bindingContext, element);
    }
};
ko.virtualElements.allowedBindings.nodes = true;
Nectarine answered 20/9, 2017 at 14:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.