Durandal 2.0 - view composition order
I have view, that has a number of child views that I am using just to break up the HTML into separate files.
index.html(index.js)
- menu.html
- header.html
- footer.html
The menu view is populated by the index view after it's loaded.
Inside the index.html I compose the menu view like this (there is no module menu.js, just html composition here):
<!--ko compose: { view: 'menu'}--><!--/ko-->
The problem is the order of the view composition.
I have an attached event wired up in index.js that then calls a function to populate the menu div that's sat in menu.html.
But, the attached view event is called before the menu.html view has been composed.
The events looks something like this from the console:
Binding views/footer
Binding views/index
binding complete: <section data-view="views/index" style="display: none;">…</section>
[Index] Main View Attached
Binding views/header
Binding views/menu
Binding views/menudropdown
So, the main view is attached before the children.
Is there a way to change the composition order, or wait for all the child views to be composed/loaded before the main view is attached/complete?
Thanks
The short answer is "no" - you can't change the composition order.
The longer answer: perhaps I've misunderstood, but it sounds a little bit suspicious that you're populating the menu div from your view model. Could you use a custom binding to do this instead? If you can do it in a binding, then you could have a look at using a Delayed Binding Handler. From the documentation:
Sometimes your binding handler needs to work with an element only after it is attached to the DOM and when the entire composition of the view is complete. An example of this is any code that needs to measure the size of an HTML element. Durandal provides a way to register a knockout binding handler so that it does not execute until the composition is complete. To do this, use
composition.addBindingHandler.
Alternatively, if you're happy with whatever code is running in your viewModel, you probably want to use the compositionComplete event rather than the attached event. From memory, the attached events run from parent to child (which is why the event is being called on index before the menu has been composed). In contrast, compositionComplete bubbles from child to parent:
Finally, when the entire composition process is complete, including any parent and child compositions, the composition engine will call the
compositionComplete(view, parent)callback, bubbling from child to parent.
You can attach a compositionComplete handler on your viewModel in the same fashion as an activate method:
// Secured Shell
define([], function () {
var viewModel = {
activate: function () {
// do stuff
},
compositionComplete: function (parent, child, settings) {
// do more stuff
debugger;
}
};
return viewModel;
});
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With