javascriptknockout.jscustom-bindingbindinghandlers

Knockout Binding with Virtual Elements Not Working


I'm working on some custom bindings, and in one I'd like to be able to show a table from some arrays of strings.

fiddle

I simplified it down to this custom binding:

ko.bindingHandlers.table = {
    init: function tableBinding(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        element.innerHTML = tableTemplate;

        var innerBindingContext = bindingContext.createChildContext(valueAccessor());

        ko.applyBindingsToDescendants(innerBindingContext, element);

        return {
            controlsDescendantBindings: true
        };
    }
};

This is the contents of template:

<!-- if: head && head.length -->
<thead>
<tr data-bind="foreach: head">
    <th data-bind="text: $rawData">not working th</th>
</tr>
</thead>
<!-- /ko -->

<tbody data-bind="foreach: rows">
<tr data-bind="foreach: $data">
    <td data-bind="text: $data">not working td</td>
</tr>
</tbody>

And some example data.

ko.applyBindings({
    table: {
        head: ["Name", "Position"],
        rows: [
            ["John", "Janitor"],
            ["Mike", "IT"],
            ["Paul", "HR"],
            ["Rick", "Coffee Fetcher"]
        ]
    }
});

I'm using Knockout 3.0, however anything that'd work on Knockout 2.x would also work here. If you look at the fiddle, the <thead> part is displaying properly, but the bindings for the body aren't. It works fine if I inline the template, and use a with binding, as in, with: table.


Solution

  • I have to confess, at the moment I am not following all you are doing here, but I can tell enough that your example will work if your if statement uses ko if: instead of just if:.

    http://jsfiddle.net/AhLzS/1/

    So instead of this:

    <!-- if: head && head.length -->
    

    go with this:

    <!-- ko if: head && head.length -->
    

    The containerless binding syntax requires <!-- ko ... --> ... <!-- /ko --> as the virtual container. Thus if an html comment syntax just has <!-- if ... -->, knockout does not do anything special.

    From the knockout documentation for the "if" binding:
    http://knockoutjs.com/documentation/if-binding.html

    The <!-- ko --> and <!-- /ko --> comments act as start/end markers, defining a “virtual element” that contains the markup inside. Knockout understands this virtual element syntax and binds as if you had a real container element.