Reputation: 21409
I am looking at the Durandal samples trying to understand how routing works.
The shell.js specifies these routes:
{ route: ['', 'knockout-samples*details'], moduleId: 'ko/index', title: 'Details...', nav: true, hash: '#knockout-samples' },
{ route: 'view-composition',moduleId: 'viewComposition/index', title: ...
under knockout-samples
:
{ route: '', moduleId: 'helloWorld/index', title: 'Hello World', type: 'intro' },
{ route: 'helloWorld', moduleId: 'helloWorld/index', title: 'Hello World', type: intro', nav: true},
What I am trying to achieve is having another hierarchy under helloWorld
. Something like this:
I tried this but no luck:
{ route: '', moduleId: 'helloWorld/index', title: 'Hello World', type: 'intro' },
{ route: 'helloWorld*details', moduleId: 'helloWorld/index', title: 'Hello World', type: 'intro', nav: true, hash:'#knockout-samples/helloWorld'}
However, this is not working.
Does Durandal routing not support this level of navigation?
Upvotes: 9
Views: 4684
Reputation: 1041
I added the child as a reference to the parent router itself. Maybe a bit sneaky, but working happily:
Top level router
define(["plugins/router"], function (router) {
// create the constructor
var ctor = function() {
};
ko.utils.extend(ctor.prototype, {
activate: function () {
//var self = this;
var map = router.makeRelative({ moduleId: "viewmodels" }).map([
{ route: "", moduleId: "index", title: "Overview", nav: true, hash: "#/", enabled: true },
{ route: "data*details", moduleId: "data/shell", title: "Data Loading", nav: true, hash: "#/data", enabled: false },
{ route: "reporting*details", moduleId: "reporting/shell", title: "Reporting", nav: true, hash: "#/reporting", enabled: true },
{ route: "query*details", moduleId: "query/shell", title: "Query", nav: true, hash: "#/query", enabled: true },
{ route: "login", moduleId: "login", title: "Login", hash: "#/login", state: "out" }
]);
return map.buildNavigationModel()
.mapUnknownRoutes("404")
.activate();
});
});
return ctor;
});
Child router
define(["plugins/router"], function (router) {
var childRouter = router.createChildRouter()
.makeRelative({
moduleId: "viewmodels/reporting",
fromParent: true
}).map([
{ route: "", moduleId: "index", title: "Reporting", nav: false, hash: "#/reporting" },
{ route: "standard", moduleId: "standard", title: "Standard Reports", nav: true, hash: "#/reporting/standard" },
{ route: "alert*details", moduleId: "alert/shell", title: "Alerts", nav: true, hash: "#/reporting/alert" }
]).buildNavigationModel();
// for alerts
router.child = childRouter;
var vm = {
router: childRouter
};
return vm;
});
Grandchild router
define(["plugins/router"], function (router) {
var grandchildRouter = router.child.createChildRouter()
.makeRelative({
moduleId: "viewmodels/reporting/alert",
fromParent: true
}).map([
{ route: "", moduleId: "index", title: "Alerts", hash: "#/reporting/alert" },
{ route: ":id", moduleId: "case", title: "Alert Details", hash: "#/reporting/alert" }
]).buildNavigationModel();
var vm = {
router: grandchildRouter
};
return vm;
});
Hope that helps.
Upvotes: 2
Reputation: 1856
When creating a 'grandchild' or 'great grandchild' or deeper child router, the trick is to reference the relative parent router, not the root router. To get a reference to the parent router, add the module that contains the parent router as a dependency to your 'grandchild' module. You can nest routers like this indefinitely. For example:
myModuleWithChildRouter.js
define(['plugins/router'], //reference to durandal root router
function(router) {
var _childRouter = router.createChildRouter();
return { myNewChildRouter: _childRouter}
}
myModuleWithGrandchildRouter.js
define(['myModuleWithChildRouter'], //reference to module with child router
function(childRouterModule) {
var _grandChildRouter = childRouterModule.myNewChildRouter.createChildRouter();
.....
}
Hope that helps!
Upvotes: 8
Reputation: 1472
To get more than one navigation level I'm doing this:
The only accesible router is the root router so to have acces to the child routers, everytime that I'm creating a child router, i store it on a module. Then, when i want to create another level, I get the child router from the module and call createChildRouter.
define([], function () {
return {
root: null,
level1: null,
level2: null
};
});
define(['plugins/router', 'routers'], function (router, routerContainer) {
var childRouter = router.createChildRouter()
.makeRelative({
moduleId: 'viewmodels/companyplussplat',
//fromParent: true
route: 'company'
}).map([
{ route: 'order/:orderID', moduleId: 'orderdetail', title: 'Order', nav: false },
{ route: 'order/:orderID*details', moduleId: 'orderdetailplussplat', title: 'Order plus splat', nav: false }
]).buildNavigationModel();
routerContainer.level1 = childRouter;
return {
activate: function () {
console.log("Activating company plus splat");
},
deactivate: function () {
console.log("Deactivating company plus splat");
},
router: childRouter
};
});
define(['plugins/router', 'routers'], function (router, routerContainer) {
//debugger;
var childRouter = routerContainer.level1.createChildRouter()
.makeRelative({
moduleId: 'orderteailplussplat',
//fromParent: true
route: 'company/order/:orderID'
}).map([
{ route: 'orderline/:orderlineID', moduleId: 'orderlinedetail', title: 'Order line detail', nav: false },
]).buildNavigationModel();
routerContainer.level2 = childRouter;
return {
activate: function (orderID) {
console.log('Activating order detail for: '+ orderID +' plus splat');
},
deactivate: function () {
console.log('Deactivating order detail plus splat');
},
router: childRouter
};
});
I hope this will help you.
Upvotes: 2
Reputation: 14995
If you are using durandal 2.0 you can set up the child router. This will allow you to create a new router under the hello world that you can chain on additional info for for sub views in your view. You can look these up on the docs but make sure you set up that router within the view so when you hit a route like
#helloworld/subview
you have already activated helloworld
Upvotes: 0