Knockout custom binding handlers: $root is undefined

二次信任 提交于 2020-01-15 03:32:16

问题


I am using a Knockout Custom Binding handler (borrowed from Creating groups with Knockout.js foreach). Within the nested markup, I'd like to reference an observable that is located on the root of the view model. However the binding fails because $root is undefined. The same markup works fine with a standard foreach binding. I don't know why the custom hander prevents using $root.

Here is the source for the binding handler :

ko.bindingHandlers.foreachGrouped = {
init: function(element, valueAccessor) {
     var groupedItems,
         options = valueAccessor();

    //create our own computed that transforms the flat array into rows/columns
    groupedItems = ko.computed({
        read: function() {
            var index, length, group,
                result = [],
                count = +ko.utils.unwrapObservable(options.count) || 1,
                items = ko.utils.unwrapObservable(options.data);

            //create an array of arrays (rows/columns)
            for (index = 0, length = items.length; index < length; index++) {
                if (index % count === 0) {
                   group = [];
                   result.push(group);
                }

                group.push(items[index]);
            }

            return result;
        },
        disposeWhenNodeIsRemoved: element
    });  

    //use the normal foreach binding with our new computed
    ko.applyBindingsToNode(element, { foreach: groupedItems });

    //make sure that the children of this element are not bound
    return { controlsDescendantBindings: true };
}
};

Here is the html markup:

Header Text: <input data-bind="value: header" />
Group count: <input data-bind="value: count" />

<div data-bind="foreachGrouped: { data: items, count: count }">
   <h1 data-bind="html: $root.header"></h1>

   <ul data-bind="foreach: $data">
       <li data-bind="text: $data"></li>
   </ul>
</div>

And here is the code used to wire up the view model:

ko.applyBindings({
  header: ko.observable("Group Header"),
      items: ko.observableArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
      count: ko.observable(4)
});

Example: http://jsfiddle.net/dk1do2vr/2/


回答1:


The problem is that the original bindingContext is lost in the handler. So when ko.applyBindingsToNode() is called, it uses a completely new context (which is empty). The handler predated when being able to specify what the binding context is, it was added in a later version of knockout. You'll need to make adjustments to the handler to be able to preserve that context.

ko.applyBindingsToNode(element, { foreach: groupedItems }, bindingContext);

So the tweaks you need to make in the handler (removed irrelevant bits to be easier to see):

ko.bindingHandlers.foreachGrouped = {
    // need to get the binding context (fifth param)
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        //...

        //use the normal foreach binding with our new computed
        ko.applyBindingsToNode(element, { foreach: groupedItems }, bindingContext); // pass in the binding context

        //...
    }
};

updated fiddle



来源:https://stackoverflow.com/questions/34456889/knockout-custom-binding-handlers-root-is-undefined

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!