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?

1

There are 1 best solutions below

0
On BEST ANSWER

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;