jstudios jstudios - 1 month ago 8
Javascript Question

Backbone.js - Pass variable from route to view/collection/model

So I'm building a mobile website and I have a directory called 'api' with various php files hat echo JSON formatted data from a remote API. I did this to avoid the cross-domain issue.

But one of the php files needs a GET parameter (i.e. id) so that I can echo the JSON data for a specific object based on it's id.

My collection will need to do this (assuming this will work):

define([
'backbone',
'models/tournaments/single'
], function(Backbone, singleModel) {
var TournamentCollection = Backbone.Collection.extend({
model: singleModel,
url: '/api/tournament.php?id=' + id,
parse: function(response) {
return response;
}
});
return TournamentCollection;
});


I have this in my router, but how do I pass the 'id' value to the view or collection:

define([
'jquery',
'underscore',
'backbone',
'views/home',
'views/tournament'
], function($, _, Backbone, HomeView, TournamentView) {

var AppRouter = Backbone.Router.extend({
routes: {
'': 'home',
'tournament/:id': 'tournament'
}
});

var initialize = function() {
var app_router = new AppRouter;

app_router.on('route:home', function() {
var homeView = new HomeView();
});

app_router.on('route:tournament', function(id) {
var tournamentView = new TournamentView({id: id});
});

Backbone.history.start();
};

return {
initialize: initialize
};
});

Answer

Couple of things:

1) Your definition of the url property of the collection will not work as id is likely not defined when defining the TournamentCollection class. You can use a function rather than a property. TournamentCollection will become something like this:

define([
    'backbone',
    'models/tournaments/single'
], function(Backbone, singleModel) {
    var TournamentCollection = Backbone.Collection.extend({
        model: singleModel,
        initialize: function (options) {
          this.id = options.id;
        },
        url: function () {
          return '/api/tournament.php?id=' + this.id
        },
        parse: function(response) {
            return response;
        }
    });
    return TournamentCollection;
});

This way you can initialize the object with an id, and later, when the url is fetched it will include the correct id.

2) I would probably initialize and fetch the collection from the router. Then from the initialize of the view, listen for that fetch to complete and ultimately re-render the view. Something like this:

define([
    'jquery',
    'underscore',
     'backbone',
     'views/home',
     'views/tournament'
 ], function($, _, Backbone, HomeView, TournamentView) {

     var AppRouter = Backbone.Router.extend({
         routes: {
             '': 'home',
             'tournament/:id': 'tournament'
         }
     });

     var initialize = function() {
         var app_router = new AppRouter;

         app_router.on('route:home', function() {
             var homeView = new HomeView();
         });

         app_router.on('route:tournament', function(id) {
             var tournaments = new TournamentCollection({ id: id });
             tournaments.fetch();
             var tournamentView = new TournamentView({ collection: tournaments });
         });

         Backbone.history.start();
     };

     return {
         initialize: initialize
     };
 });

 // Tournament View define stuff
 var TournamentView = Backbone.View.extend({
   initialize: function () {
     this.listenTo(this.collection, 'sync', this.render);
   },
   render: function () {
     //...
   }
 });
 return TournamentView

hope that helps. :)