Reputation: 5643
I am using a custom menu
binding for the jquery ui menu widget. Inside the HTML for my menu, I am using a component. It looks something like this:
<ul data-bind="menu: {...}">
<!-- ko foreach: menuComponents -->
<li>
<div data-bind="component: $data"></div>
</li>
<!-- /ko -->
</ul>
My custom binding is using applyBindingsToDescendents()
to resolve the bindings inside the ul
before initializing the menu. This is a simplified version of my binding.
ko.bindingHandlers.menu = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
ko.applyBindingsToDescendants(bindingContext, element);
$(element).menu();
return {controlsDescendantBindings: true};
}
};
The problem is that components are loaded asynchronously. I am using a custom component loader, but I'm not sure if that matters. The side effect is that the component
binding isn't resolved until the component is loaded. So the load order looks like this:
applyBindingsToDescendents
Since the component isn't initialized until after bindings are applied, my menu isn't rendering properly.
Is there any way I can force component descendant bindings to be applied synchronously? Or is there a way I can detect when they are applied and refresh the menu widget?
Upvotes: 1
Views: 613
Reputation: 5643
My working solution at the moment is to avoid the use of components completely. I simply use the template binding and apply the view models manually.
<ul data-bind="menu: {...}">
<!-- ko foreach: menuItems -->
<li>
<div data-bind="template: {name: $data.template, data: $data.data}"></div>
</li>
<!-- /ko -->
</ul>
I tried using the synchronous option for my components, but the problem is that it does not gurantee synchronous operation. Another solution was to bind my menu in a setTimeout
call, but I avoided this solution because it can potentially cause other issues. But that would have looked like this:
ko.bindingHandlers.menu = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
ko.applyBindingsToDescendants(bindingContext, element);
setTimeout(function() {
$(element).menu();
});
return {controlsDescendantBindings: true};
}
};
Upvotes: 0