Is there a way to apply component bindings after the ko.applyBindings() call?
The point is, I use requireJS to load my modules/components async. So how do I know that all bindings are registered?
ko.applyBindings();
ko.components.register('my-component',
{
viewModel: function() {
this.name = ko.observable('My Name');
},
template: '<input type="text" data-bind="value: name"></input>'
}
);
// Moving it here, it works:
// ko.applyBindings();
There are a couple of pieces that you could use to dynamically understand and load components.
1- A custom component loader
You could create a component loader that understands from a component name, which files to require.
For sake of an example, lets say that any component that starts with
my-
, we want to require from thecomponents
directory by convention.It could look like:
If the default loader can't find a component (not registered yet), then this one would kick in.
2- We would still need to handle custom elements, as these run off of the registration as well. The documentation describes the
ko.components.getComponentNameForNode
method that could be overriden to dynamically convert an element tag to component name.In our case, this could look like:
Here is a fiddle that puts these together with require.js: http://jsfiddle.net/rniemeyer/tgm8wn7n/
Also, take note of the IE6-8 warning here, as it would affect dynamically understanding the custom elements.
Alternatively, you would need to ensure that all of your components are registered before that component is bound in the UI (not necessarily at the time of the initial applyBindings, but as soon as a component is encountered that needs to be bound).
To expand on RP Niemeyer's suggestion to ensure all components are registered before the bindings is hit, I have done this successfully in the past to load components I only need rarely.:
You can ensure that the component binding is not attempted before you have registered the component by using it from within a property of a root or controller style top level model, and wrapping it in a
with
binding. KO will not evaluate anything inside thewith
until the property is assigned.This is easier to explain with an example than words!
So here is your code, demonstrating that
applyBindings
is called early, then using a timeout to simulate later loading of code relying on the component:Markup:
Code:
Working Fiddle: http://jsfiddle.net/whelkaholism/dhaox1ae/