Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure Durandal.js to have multiple areas with views and viewmodels in same folder?

I'm working with an SPA that will have many different areas, each with several pages. My boss really doesn't want dozens of views and viewmodels folders with a few items in each one. How do I configure Durandal to use something like this:

/App/Areas/Login/
                 login.html
                 login.js
/App/Areas/Here/
                 subpage1.html
                 subpage1.js
                 subpage2.html
                 subpage2.js
                 subpage3.html
                 subpage3.js
/App/Areas/There/
                 subpage1.html
                 subpage1.js
                 subpage2.html
                 subpage2.js
                 subpage3.html
                 subpage3.js

I've looked at other similar questions about Areas, but don't quite know how to start. Thanks.

like image 547
Jammerms Avatar asked Jun 14 '13 21:06

Jammerms


Video Answer


2 Answers

You can have any folder structure your heart desires. Durandal does not impose any folder structure on your application but it does have a default convention which is completely overridable.

If you are using Durandals router then you will want to look into how to configure it to find modules. There are many ways of doing this, I prefer to create my own convention by overriding the router.autoConvertRouteToModuleId.

If you are not using the router plugin then you will have to manage the uris for your modules yourself and this is done by following requirejs' convention and using this convention along w/ durandals composition module.

Also, you can override how it finds the views to bind to your modules by overriding the viewlocators convention. Durandal provides an very simplistic way of structuring small applications right out of the box but if you need to build larger applications then it is recommended you create your own conventions.

like image 107
Evan Larsen Avatar answered Sep 28 '22 09:09

Evan Larsen


The 'samples' project that ships with Durandal 2.0 is an example of how to accomplish what you want without having to customize the router. The example below is from that project (and also shows how to use a 'child' router). Notice how moduleId parameters in the call to 'makeRelative' and route config combine to give you whatever folder structure you want.

app/ko/index.js

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: 5},
        { route: 'clickCounter',    moduleId: 'clickCounter/index',     title: 'Click Counter',         type: 'intro',      nav: 4},
        { route: 'simpleList',      moduleId: 'simpleList/index',       title: 'Simple List',           type: 'intro',      nav: 3 },
        { route: 'betterList',      moduleId: 'betterList/index',       title: 'Better List',           type: 'intro',      nav: 2},
        { route: 'controlTypes',    moduleId: 'controlTypes/index',     title: 'Control Types',         type: 'intro',      nav: 1 },
        { route: 'collections',     moduleId: 'collections/index',      title: 'Collection',            type: 'intro' ,     nav: 99 },
        { route: 'pagedGrid',       moduleId: 'pagedGrid/index',        title: 'Paged Grid',            type: 'intro',      nav: 98 },
        { 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: 1}
    ])
    .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';
        });
    })
};

});

like image 24
Zac Morris Avatar answered Sep 28 '22 07:09

Zac Morris