Reputation: 1541
This is kind of related to my recent question about multiple views within one page. I started with the Durandal sample knockout shell and attempted to extract the navigation menu on the left into its own "navList.html/navList.js" view/viewmodel.
I created navList.html and navlist.js:
<ul class="nav nav-list">
<li class="nav-header">Basic Examples</li>
<!--ko foreach: introSamples-->
<li data-bind="css: { active: isActive }">
<a data-bind="attr: { href: hash }, text: title"></a>
</li>
<!--/ko-->
<li class="nav-header">Detailed Examples</li>
<!--ko foreach: detailedSamples-->
<li data-bind="css: { active: isActive }">
<a data-bind="attr: { href: hash }, text: title"></a>
</li>
<!--/ko-->
</ul>
define(['plugins/router', 'knockout'], function (router, ko) {
var childRouter = router.createChildRouter()
.makeRelative({
moduleId: 'ko',
fromParent: true
}).map([
{ route: '', moduleId: 'helloWorld/index', title: 'Hello World', type: 'intro' },
{ route: 'helloWorld', moduleId: 'helloWorld/index', title: 'Hello World', type: 'intro', nav: true },
{ route: 'clickCounter', moduleId: 'clickCounter/index', title: 'Click Counter', type: 'intro', nav: true },
{ route: 'simpleList', moduleId: 'simpleList/index', title: 'Simple List', type: 'intro', nav: true },
{ route: 'betterList', moduleId: 'betterList/index', title: 'Better List', type: 'intro', nav: true },
{ route: 'controlTypes', moduleId: 'controlTypes/index', title: 'Control Types', type: 'intro', nav: true },
{ route: 'collections', moduleId: 'collections/index', title: 'Collection', type: 'intro', nav: true },
{ route: 'pagedGrid', moduleId: 'pagedGrid/index', title: 'Paged Grid', type: 'intro', nav: true },
{ route: 'animatedTrans', moduleId: 'animatedTrans/index', title: 'Animated Transition', type: 'intro', nav: true },
{ route: 'contactsEditor', moduleId: 'contactsEditor/index', title: 'Contacts Editor', type: 'detailed', nav: true },
{ route: 'gridEditor', moduleId: 'gridEditor/index', title: 'Grid Editor', type: 'detailed', nav: true },
{ route: 'shoppingCart', moduleId: 'shoppingCart/index', title: 'Shopping Cart', type: 'detailed', nav: true },
{ route: 'twitterClient', moduleId: 'twitterClient/index', title: 'Twitter Client', type: 'detailed', nav: true }
]).buildNavigationModel();
return {
router: childRouter,
introSamples: ko.computed(function () {
return ko.utils.arrayFilter(childRouter.navigationModel(), function (route) {
return route.type == 'intro';
});
}),
detailedSamples: ko.computed(function () {
return ko.utils.arrayFilter(childRouter.navigationModel(), function (route) {
return route.type == 'detailed';
});
})
};
});
...which are pretty much identical copies of the original index.html and index.js files.
I then turned index.js into this:
define(['ko/navList'], function(nav) {
return {
router: nav.router
};
});
and index.html into this:
<div class="container-fluid knockout-samples">
<div class="row-fluid">
<div class="span2 well">
<!--ko compose: {view: navList,
transition: 'entrance'} -->
<!--/ko-->
</div>
<div class="span10">
<!--ko router: { transition:'entrance', cacheViews:true }--><!--/ko-->
</div>
</div>
</div>
...which is not a major change. All I'm trying to achieve at this point is education via tinkering. I figured that if I could deconstruct/reconstruct a working example I'd be a step further along my line of understanding of how to structure my app.
Of course, where this goes wrong is on the binding to navList. It appears that despite being told to go and look for navList as a view, it's treating it as part of the index.js model as far as I can tell so I get this in the console window:
Binding ko/index
Object {router: Object, __moduleId__: "ko/index"}
system.js:75
Unable to parse bindings.
Bindings value: compose: {view: navList,
transition: 'entrance'}
Message: navList is not defined;
View: ko/index;
ModuleId: ko/index
Could some kind soul please explain the fundamental understanding issue I have here please?
Solution: As pw kad suggested, using the container "data-bind" syntax in index.html instead of containerless as I was trying to do has fixed the problem. The code is now:
<div class="container-fluid knockout-samples">
<div class="row-fluid">
<div class="span2 well" data-bind="compose: 'ko/navList'"></div>
<div class="span10">
<!--ko router: { transition:'entrance', cacheViews:true }--><!--/ko-->
</div>
</div>
</div>
Upvotes: 1
Views: 1805
Reputation: 14995
Use ko compose: 'viewmodels/navList' to instantiate the view model and view from your parent view. This allows Durandal to map using the default viewLocator in your app/viewmodels/ folder.
check the docs for more info
http://durandaljs.com/documentation/Using-Composition/
Upvotes: 1