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/
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.So the tweaks you need to make in the handler (removed irrelevant bits to be easier to see):
updated fiddle