Search code examples
javascriptphpjqueryjsonbackbone.js

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
    };
});

Solution

  • 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. :)