Problem with routing in Durandal 2

3,349 views
Skip to first unread message

Stian Kroknes

unread,
Aug 20, 2013, 9:12:41 AM8/20/13
to duran...@googlegroups.com
 Hi,

I have upgraded from Durandal from 1.2 to 2.0 and my app almost works. But I have an issue with the router, I think... When the default page is loaded after app start an infinite loop occurs; debug outputs multiple 'Navigation Complete events'..
To my understadning the default page is the route mapping with title 'Home'; route definition ''.

My main.js
requirejs.config({
    paths: {
        'text': '../Scripts/text',
        'durandal': '../Scripts/durandal',
        'plugins': '../Scripts/durandal/plugins'
    },
    urlArgs: "bust=" + (new Date()).getTime() // TODO
});
 
define('jquery', function () { return jQuery; });
define('knockout', ko);
 
define(['durandal/app', 'durandal/viewLocator', 'durandal/system', 'services/antiforgery', 'services/authentication', 'plugins/router', 'plugins/dialog'],
    function (app, viewLocator, system, antiforgery, authentication, router, dialog) {
        app.title = 'Test';
 
        //specify which plugins to install and their configuration
        app.configurePlugins({
            router: true,
            dialog: true,
            widget: true
        });
 
        //>>excludeStart("build", true);
        system.debug(true);
        //>>excludeEnd("build");
 
        antiforgery.addAntiForgeryTokenToAjaxRequests();
        authentication.handleUnauthorizedAjaxRequests(function () {
            dialog.showMessage('You are not authorized, please login')
                .then(function () {
                    router.navigate('#/account/login');
                });
        });
 
        app.start().then(function () {
            //Show the app by setting the root view model for our application with a transition.
            app.setRoot('shell');
        });
    });

My shell.js

define(['plugins/router', 'durandal/app'], function (router, app) {
    return {
        activate: function () {
            router.map([
                { route: '', moduleId: 'home/index', title: 'Home' },
                { route: 'account/login', moduleId: 'account/login', title: 'Login', nav: false },
                { route: 'account/logoff', moduleId: 'account/logoff', title: 'Logoff', nav: false },
                { route: 'tasks*details', moduleId: 'tasks/index', title: 'Tasks', nav: true, hash: '#tasks' }
            ]).buildNavigationModel();
 
            return router
                .activate();
        },
        router: router
    }
});

My shell.html
<div>
    <!--ko compose: { model: router.activeItem, view:'header.html', mode:'templated' }-->
    <!--/ko-->
 
    <div class="page-host">
        <!--ko router: { cacheViews: false}-->
        <!--/ko-->
    </div>
 
</div>

And in a folder 'home' i have index.js and index.html.
Index.js
define(['plugins/router', 'durandal/system', 'services/authentication'], function (router, system, authentication) {
        return {
        router: router,
        title: 'Home',
        logoff: function () {
            console.log('logoff');
            authentication.logoff();
            router.navigate('#/account/login');
        },
        attached: function (view) {
            system.log('Lifecycle : attached : hello');
// Using jQuery Mobile
             $("div[data-role=page]").page("destroy").page();         }     }; });
And finally the index.html
<ul data-role="listview" data-inset="true">
    <li data-role="list-divider">Navigation</li>
    <li>
        <a data-bind="click: logoff">Logout</a>
    </li>
 
    <!-- ko foreach: router.navigationModel -->
    <li data-bind="css: { active: isActive }">
        <a data-bind="attr: { href: hash }, html: title"></a>
    </li>
    <!-- /ko -->
 
</ul>

Console debug output:

... and so on...

Other pages load fine and routing works.

I can not find a solution to my problem and I would appreciate your help.

Thanks


Rob Eisenberg

unread,
Aug 20, 2013, 10:42:43 AM8/20/13
to Stian Kroknes, duran...@googlegroups.com
If you can send me a simple repro, zipped up so I can run it and see the behavior, that would help me determine if there's a bug a little easier/quicker.


--
You received this message because you are subscribed to the Google Groups "DurandalJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to durandaljs+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Rob Eisenberg,
President - Blue Spire
www.durandaljs.com
Message has been deleted

Stian Kroknes

unread,
Aug 21, 2013, 4:43:25 AM8/21/13
to duran...@googlegroups.com, Stian Kroknes, r...@bluespire.com
I have uploaded some code to reproduce my problem, https://github.com/stiankroknes/durandal-router-problem.

Rob Eisenberg

unread,
Aug 21, 2013, 12:56:08 PM8/21/13
to Stian Kroknes, duran...@googlegroups.com
You need to serve the files from a web server. Otherwise, the browser will complain with the security error above. Only Firefox works directly against the file system. Docs on that here: http://durandaljs.com/documentation/Manual-Setup/

Stian Kroknes

unread,
Aug 21, 2013, 1:23:43 PM8/21/13
to r...@bluespire.com, duran...@googlegroups.com
My bad, I deleted the post including the cross origin error... I did not suppose to include that in the post as it was not the problem. 

When hosted and opened in Chrome you will see the infinite loop in console. 

Thanks

-Stian

Rob Eisenberg

unread,
Aug 21, 2013, 1:24:02 PM8/21/13
to Stian Kroknes, duran...@googlegroups.com
Ok. I'll take a look. Probably tomorrow...

Stian Kroknes

unread,
Aug 24, 2013, 3:50:06 AM8/24/13
to duran...@googlegroups.com
Hi,

I am curious if you have looked at the problem? :-)

-stian

Rob Eisenberg

unread,
Aug 24, 2013, 1:16:24 PM8/24/13
to Stian Kroknes, duran...@googlegroups.com
Not yet. Soon.


--
You received this message because you are subscribed to the Google Groups "DurandalJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to durandaljs+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Mike Cottingham

unread,
Aug 29, 2013, 5:39:38 PM8/29/13
to duran...@googlegroups.com, Stian Kroknes, r...@bluespire.com
I am seeing this same issue with my project.

Console Output:

Navigation Complete
Object {activatefunctiondeactivatefunctioncompositionCompletefunctionsongwriterfunctionsongsfunction}
Object {fragment"songwriter/1"queryStringnullconfigObjectparamsArray[1]queryParamsnull}
system.js:75
Activating
Object {activatefunctiondeactivatefunctioncompositionCompletefunctionsongwriterfunctionsongsfunction}
system.js:75
Navigation Complete
Object {activatefunctiondeactivatefunctioncompositionCompletefunctionsongwriterfunctionsongsfunction}
Object {fragment"songwriter/1"queryStringnullconfigObjectparamsArray[1]queryParamsnull}
system.js:75
Activating
Object {activatefunctiondeactivatefunctioncompositionCompletefunctionsongwriterfunctionsongsfunction}
system.js:75
Navigation Complete
Object {activatefunctiondeactivatefunctioncompositionCompletefunctionsongwriterfunctionsongsfunction}
Object {fragment"songwriter/1"queryStringnullconfigObjectparamsArray[1]queryParamsnull}
system.js:75
Activating
Object {activatefunctiondeactivatefunctioncompositionCompletefunctionsongwriterfunctionsongsfunction}
system.js:75
Navigation Complete
Object {activatefunctiondeactivatefunctioncompositionCompletefunctionsongwriterfunctionsongsfunction}
Object {fragment"songwriter/1"queryStringnullconfigObjectparamsArray[1]queryParamsnull}

Are there any ideas as to what this is?

Chad Corrin

unread,
Aug 29, 2013, 11:59:58 PM8/29/13
to duran...@googlegroups.com
I had the same issue, not sure why but if you expose the router in your child viewmodels it will loop like that over and over. Instead just expose the routers navigationModel in your other viewmodels outside of shell.js and you can still access the routetable. The problem only occurs when you expose the entire router outside of the shell module.

return {
   navigationModel: router.NavigationModel

Rob Eisenberg

unread,
Aug 30, 2013, 12:05:21 AM8/30/13
to Chad Corrin, duran...@googlegroups.com
AHA!!!!!!

That may be the issue. Are you exposing the root router as a property called "router" in a child view model?!
If that is the commonality in all of these case....then I can probably fix this pretty easily.

@All Please let me know.


--
You received this message because you are subscribed to the Google Groups "DurandalJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to durandaljs+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Mike Cottingham

unread,
Aug 30, 2013, 12:06:50 AM8/30/13
to r...@bluespire.com, duran...@googlegroups.com, Chad Corrin

I definitely am in my viewmodels...

Rob Eisenberg

unread,
Aug 30, 2013, 12:13:13 AM8/30/13
to Mike Cottingham, duran...@googlegroups.com, Chad Corrin
Excellent. I can see it in Stian's code sample above, so I think that makes three confirmations of the same pattern. I've got someone else who reported the same issue, so we'll see if they have the same thing. My guess is, yes. I now understand the problem and can get it fixed pretty quick I believe. I will update this when the fix is in the patch branch. I'm not going to do it now...because it's late and I need some sleep :) But, it will be first thing in the morning. Thank you for your patience.

Chad Corrin

unread,
Aug 30, 2013, 12:17:16 AM8/30/13
to r...@bluespire.com, Mike Cottingham, duran...@googlegroups.com
Thank Rob! I'm loving this framework, and 2.0 is even better! :)

Mike Cottingham

unread,
Aug 30, 2013, 12:19:24 AM8/30/13
to r...@bluespire.com, Chad Corrin, duran...@googlegroups.com

Much appreciated Rob!

I was starting to think that my code always had this issue and that the new verbosity level of 2.0.0 has just exposed it.

Rob Eisenberg

unread,
Aug 30, 2013, 10:47:51 AM8/30/13
to Mike Cottingham, Chad Corrin, duran...@googlegroups.com
Ok...The fix is in branch Version-2.0.1. Just grab the latest version of router.js from there. Please let me know if your issues are resolved. Thank you.

Mike Cottingham

unread,
Aug 30, 2013, 12:52:54 PM8/30/13
to duran...@googlegroups.com, Mike Cottingham, Chad Corrin, r...@bluespire.com
Thanks Rob!

I just plugged in the new router code and everything works great again!  Thank you for fixing this so quickly!


On Friday, August 30, 2013 8:47:51 AM UTC-6, EisenbergEffect wrote:
Ok...The fix is in branch Version-2.0.1. Just grab the latest version of router.js from there. Please let me know if your issues are resolved. Thank you.

sairaju....@gmail.com

unread,
Sep 16, 2014, 3:40:27 AM9/16/14
to duran...@googlegroups.com
Hi Mike and Rob

I too had the same router issues which is not resolving in project.please guid me how to fix that. here are my files

My Main.js

requirejs.config({
    paths: {
        'text': '../Scripts/text',
        'durandal': '../Scripts/durandal',
        'plugins': '../Scripts/durandal/plugins',
        'transitions': '../Scripts/durandal/transitions'
    }
});

define('jquery', function() { return jQuery; });
define('knockout', ko);

define(['durandal/system', 'durandal/app', 'durandal/viewLocator'],  function (system, app, viewLocator) {
    //>>excludeStart("build", true);
    system.debug(true);
    //>>excludeEnd("build");

    app.title = 'Durandal Starter Kit';

    app.configurePlugins({
        router: true,
        dialog: true,
        widget: true
    });

    app.start().then(function() {
        //Replace 'viewmodels' in the moduleId with 'views' to locate the view.
        //Look for partial views in a 'views' folder in the root.
        viewLocator.useConvention();

        //Show the app by setting the root view model for our application with a transition.
        app.setRoot('viewmodels/shell', 'entrance');
    });
});


Shell.js
------------
define(['plugins/router', 'durandal/app'], function (router, app) {
    return {
        router: router,
        search: function() {
            //It's really easy to show a message box.
            //You can add custom options too. Also, it returns a promise for the user's response.
            app.showMessage('Search not yet implemented...');
        },
        activate: function () {

            router.makeRelative({ moduleId: 'viewmodels' });

            router.map([
                //{ route: '', title:'Welcome', moduleId: 'viewmodels/welcome', nav: true },
                //{ route: 'flickr', moduleId: 'viewmodels/flickr', nav: true },
                //{ route: '', title:'Welcome', moduleId: 'viewmodels/welcome', nav: true },
                { route: '', title: 'Login', moduleId: 'account/login', nav: true },
                { route: 'users/adduser', title: 'Add User', moduleId: 'users/adduser', nav: true },
                { route: 'users/deleteuser', title: 'Delete User', moduleId: 'users/deleteuser', nav: true },
                { route: 'users/detailuser', title: 'Details User', moduleId: 'users/detailuser', nav: true },
                { route: 'users/edituser', title: 'Edit User', moduleId: 'users/edituser', nav: true },
            ]).buildNavigationModel();

            return router.activate();
        }
    };
});

Shell.html
-----------------
<div>
     <div data-bind="compose: 'viewmodels/header'"></div>
    <div class="container-fluid page-host">
    <!--ko compose: { 
        model: router.activeItem, //wiring the router
        afterCompose: router.afterCompose, //wiring the router
        transition:'entrance', //use the 'entrance' transition when switching views
        cacheViews:false //telling composition to keep views in the dom, and reuse them (only a good idea with singleton view models)
    }--><!--/ko-->
</div>
</div>

login.js
----------------
define(function (require) {
    var app = require('durandal/app');
    var router = require('plugins/router');

    return {
        convertRouteToHash: router.convertRouteToHash,
        userToAdd: {
            username: ko.observable(),
            pwd: ko.observable()
        },

        activate: function () {
            var then = this;

            then.userToAdd.username("Admin");
            then.userToAdd.pwd("");
        },
        
        loginUser: function () {
            //alert("asdfa");
            //console.log('goTo clicked');
            //router.navigateTo("#/users/detailuser");
            //router.navigate("#users/detailuser",false);

            router.navigate("users/detailuser");
            

        }
    };

});


login.html
----------------
<div id="login">
        <div class="container">
            <div class="jumbotron">
                <div class="row">
                    <div class="col-lg-3"></div>
                    <div class="col-lg-6">
                        <form class="form-horizontal">
                            <div class="page-header">
                                <h4>Log in with your credentials</h4>
                            </div>
                            <div class="form-group">
                                <label class="control-label col-lg-4" for="username">User Name</label>
                                <div class="col-lg-8">
                                    <input class="form-control" type="text" data-bind="value: userToAdd.username" placeholder="User Name">
                                </div>
                            </div>
                            <div class="form-group">
                                <label class="control-label col-lg-4" for="email">Password</label>
                                <div class="col-lg-8">
                                    <input class="form-control" type="password" data-bind="value: userToAdd.pwd" placeholder="Password">
                                </div>
                            </div>
                        
                            <div class="col-lg-offset-4 mart2">
                                <button type="submit" class="btn btn-primary" data-bind="click: loginUser">Sign In</button>
                                <button type="reset" class="btn btn-default">Reset</button>   
                                                         
                            </div>
                        </form>                      
                    </div>
                    <div class="col-lg-3"></div>
                </div>
            </div>
        </div>
    </div>

    

Now i want to move from login to detailuser page

Thanks & Regards
Sairaju.N


------------
Reply all
Reply to author
Forward
0 new messages