0

I'm using the following router in my app:

app.Router = Backbone.Router.extend({
    // define the route and function maps for this router
    routes : {
        "" : "showLogin",
        // Sample usage: http://ServerManager/
        "login" : "login",
        // Sample usage: http://ServerManager/#login
        "logout" : "logout",
        // Sample usage: http://ServerManager/#logout
        "folders" : "listFolders",
        // Sample usage: http://ServerManager/#folders
        "folders/:name" : "showFolder",
        // Sample usage: http://ServerManager/#folders/System
        "*other" : "defaultRoute"
        // Sample usage: http://ServerManager/#badHash
    },
    showLogin : function() {
        console.log("Home page loaded. Redirecting to #login page.");
        this.navigate("login", {trigger: true, replace: true});
    },
    login : function() {
        //console.log("login route fired");
        // delete sessionStorage items and load a new loginview
        this.changePage(new app.LoginView()); 
    },
    logout : function() {
        //console.log("logout route fired");
        // Clear the token and other session items from sessionStorage
        sessionStorage.clear();
        this.navigate("login", {trigger: true, replace: true});
    },
    listFolders : function() {
        //console.log("listFolders route fired.")
        if (app.folderView === undefined) {
            console.log("creating new app.folderView");
            app.folderView = new app.FolderView();
        }
        else {
            console.log("using existing app.folderView");
        }
        this.changePage(app.folderView);
    },
    showFolder : function(name) {
        console.log( app.router.routes[Backbone.history.fragment] );
        //console.log("showFolder route fired.")
        this.changePage(new app.ServiceView({folder : name}));
        console.log( app.router.routes[Backbone.history.fragment] );
        //app.router.navigate("folder/" + name, {trigger: false});
    },
    defaultRoute : function() {
        alert("Error. Page doesn\'t exist.");
    },
    changePage : function(page) {
        $(page.el).attr("data-role", "page");
        page.render();
        $("body").append($(page.el));
        var transition = $.mobile.defaultPageTransition;
        $.mobile.changePage($(page.el), {changeHash : true, transition : transition});
    }
});

If I use

app.router.navigate("folders", {trigger: true, replace: true});

it successfully sends the app to server/#folders, but when I pass

app.router.navigate("folders/" + id, {trigger: true, replace: true});

it triggers the root of the app and loads my login page. I can see the correct URL (e.g. server/folders/folder1) temporarily flash before the redirect happens. Any ideas as to what's happening here?

Evan
  • 456
  • 7
  • 16
  • I'm not sure what the issue is but I think that the [jquery-mobile-router](https://github.com/azicchetti/jquerymobile-router) plugin was originally created because JQM didn't play nice with backbone.js. – Jack Sep 10 '12 at 13:32

1 Answers1

1

Backbone routers expect more generic routes last.

Set-up the folders/:id route followed by the folders route.

UPDATE

Actually, after thinking about it, this may not be the case. Can you post console output? Is it calling the correct function?

Perhaps the $.mobile ... changeHash: true is conflicting. You should probably only have one of the frameworks change the url hash for you.

nickaknudson
  • 4,769
  • 2
  • 15
  • 16
  • I tried changing the order of the routes and setting changeHash to false, but same result. It temporarily loads the page, then redirects to the app root. – Evan Sep 07 '12 at 20:24
  • This "more generic routes last" stuff that used to be in the Backbone docs was nonsense, [there is no well defined key order in a JavaScript object](http://stackoverflow.com/a/10624559/479863). You'll notice that the Backbone router docs no longer say anything about the order of things in `routes` (at least I can't find it anymore). – mu is too short Sep 07 '12 at 20:37
  • OTOH, I think you might be right that jQuery Mobile and Backbone are fighting each other. – mu is too short Sep 07 '12 at 21:24
  • I've got all jqm routing and navigation disabled. If I comment out the navigate line in my router showLogin function then all works fine (except then it won't show the login page when I hit the root of the app). – Evan Sep 08 '12 at 13:08
  • @muistooshort the source still says that it follows the concept of "more generic routes last." In fact it only worked for me when I mapped rails routes to backbone in this manner, i.e. `posts/:id` AFTER `posts/new` – nickaknudson Sep 12 '12 at 18:14
  • @Evan just map the `""` route to `login()` such that you don't even have a `showLogin()` function. – nickaknudson Sep 12 '12 at 18:18
  • The source is mistaken about how JavaScript works, there is no well defined "last" in a JavaScript object. The only way to get your routes checked in a specific and reliable order is to add them manually by calling [`route`](http://backbonejs.org/#Router-route). Assuming that the source-order of things in `routes` means anything is a gamble that you will lose sooner or later. – mu is too short Sep 12 '12 at 18:31