3

I use RequireJS to organize my Backbone app and my Router module is as follows:

define([
'jquery',
'underscore',
'backbone',
'collections/todos',
'views/todosview'
], function($, _, Backbone, TodosCollection, TodosView){
var AppRouter = Backbone.Router.extend({

    routes: {
        "": "index",
        "category/:name": "hashcategory"  
    },

    initialize: function(options){
        // Do something
    },

    index: function(){
        // Do something
    },

    hashcategory: function(name){
        // Do something
    }
});

var start = function(){ 
    p = $.ajax({
        url: 'data/todolist.json',
        dataType: 'json',
        data: {},
        success: function(data) {

            var approuter = new AppRouter({data: data});
            Backbone.history.start();
        }
    });     
};

return {
    start: start
};
});

And I have another app module which uses Router.start() to trigger the whole app. Now, in my Backbone.View module, I want to use Router.navigate to trigger the route in this Router module. The starting part of my View module is as follows:

define([
'jquery',
'underscore',
'backbone',
'models/todo',
'views/todoview',
'text!templates/todo.html',
'router'
], function($, _, Backbone, TodoModel, TodoView, todoTemplate, Router){...

But when I want to use Router in this module, it always says Router is not defined. What I want to do is to call Router.navigate when some action is fired in this View module. So how could I achieve this?

chaonextdoor
  • 5,019
  • 15
  • 44
  • 61

3 Answers3

8

Create a separate module that is included in every other module you use -- it will simply create an object you can use to attach the router instance and call it from any view or module you wish later on. (in addition to other things like store data and pass around to other modules easily)

Include this module in the router module you have pasted first here. Remove the start function from the bottom of your router module. And just return AppRouter at the end of that file.

In your app module where you end up starting backbone and creating the router, you can saved the router initialization to that shared object I was referring to.

IE,

shared.js -> no deps, but creates YourObject = {}; and returns YourObject router.js -> has shared.js included app.js -> has shared.js included and router.js. app sets up router and saves to YourObject.router then starts backbone. You can now call YourObject.router.navigate() from any other module where you require this shared.js module

PStamatiou
  • 151
  • 4
  • I'm a little bit confused about the content of app.js.Could you please write more about it? Thx! – chaonextdoor Apr 28 '12 at 13:09
  • app.js would be where your actual backbone app gets started (like your "start" function above). just basic app logic. It wouldn't return anything and it wouldn't be included in any other modules, it is just where the app starts. – PStamatiou Apr 28 '12 at 21:05
  • What you mean is to move `start` function from `route` module to `app` module? And after that, I should put the router instance created in `app` module, which is the variable `approuter` in my case, in the `YourObject{}` in share.js, And then I can use shared.js everywhere else. Am I right? – chaonextdoor Apr 28 '12 at 23:40
3

Here's an educated guess ;)

You probably have a cyclic requirement. You require the router module in your view module and also require the view module in your router module.

This kinda smells like bad design. Your router module probably needs to know about your views/models in order to instantiate them and render them. Your views though should be ignorant that there is a router somewhere that will create them. All they should be doing is providing links that would trigger the router's routes.

ggozad
  • 13,105
  • 3
  • 40
  • 49
  • As you said, All they should be doing is **providing links** that would trigger the router's routes. That's the problem. I want to associate router's routes with some other actions instead of clicking links. So I don't want to use links here and I have to use `Router.navigate()`function to trigger the router's routes. As the **some other actions** will definitely be fired in View module. So, based on my knowledge, I have to use `Router.navigate()` in my View module. Or maybe there are other ways to fix this. Or maybe I have a misunderstanding towards RequireJS and/or Backbone. – chaonextdoor Apr 28 '12 at 11:30
  • What you then do is fire events that trigger the routes! – ggozad Apr 28 '12 at 20:53
  • The router listens to changes on the location.href and location.hash right? So changing the location should work. Personally I had a view redirect to the logout page with `window.location.replace('#login')` – andho Nov 27 '12 at 06:29
  • Btw, I am also changing an app I made with backbone.js and jqm to work with require.js. I had used a global `app` variable which I used in views, which I would probably need to change. – andho Nov 27 '12 at 06:31
0

What about using

Backbone.history.navigate('',{trigger:true});

gunalmel
  • 411
  • 6
  • 7