Backbone passing a model to Router

2019-04-23 23:15发布

问题:

I'm developing an application for android using require js and Backbone. I have to pass a model taken from a collection via touchend event to the router. How can I do it?

define(["jquery", "underscore","backbone","handlebars", "views/CinemaView", "models/CineDati",  "text!templates/listacinema.html"],

function($,_,Backbone,Handlebars,CinemaView, CineDati, template){   
  var ListaCinemaView = Backbone.View.extend({
    template: Handlebars.compile(template),
    events: {
        "touchend" : "Details"
    },  
    initialize : function (){
        var self = this;
        $.ajax({
            url: 'http://www.cineworld.com/api/quickbook/cinemas',
            type: 'GET',
            data: {key: 'BwKR7b2D'},
            dataType: 'jsonp', // Setting this data type will add the callback parameter for you
            success: function (response, status) {
                // Check for errors from the server
                if (response.errors) {
                    $.each(response.errors, function() {
                        alert('An error occurred. Please Try Again');
                    });
                } else {

                    $.each(response.cinemas, function() {
                        var cinema = new CineDati();
                        cinema.set({ id : this.id, name : this.name , cinema_url : this.cinema_url, address: this.address, postcode : this.postcode , telephone : this.telephone });
                        self.model.add([cinema]);

                    });
                    self.render();
                }}
        });


    },

    events : {
        "#touchend" : Dettagli
    },      

    render : function(){
        $(this.el).empty();

        $(this.el).html(template).append(
            _.each(this.model.models, function (cinema) {
              $("#lista").append(new CinemaView({
                          model: cinema
               }).render().el); }, this));

          return this;
    },

     Dettagli : function(){ 

        Backbone.history.navigate( this.model , {trigger: "true"});
    }


    });
    return ListaCinemaView;

});    

回答1:

You need to override the Backbone's navigate function as following:

var Router = Backbone.Router.extend({
    routeParams: {},
    routes: {
        "home": "onHomeRoute"
    },
    /*
     *Override navigate function
     *@param {String} route The route hash
     *@param {PlainObject} options The Options for navigate functions.
     *              You can send a extra property "params" to pass your parameter as following:
     *              {
     *               params: 'data'
     *              }
     **/
    navigate: function(route, options) {
        var routeOption = {
                trigger: true
            },
            params = (options && options.params) ? options.params : null;
        $.extend(routeOption, options);
        delete routeOption.params;

        //set the params for the route
        this.param(route, params);
        Backbone.Router.prototype.navigate(route, routeOption);
    },

    /*
     *Get or set parameters for a route fragment
     *@param {String} fragment Exact route hash. for example:
     *                   If you have route for 'profile/:id', then to get set param
     *                   you need to send the fragment 'profile/1' or 'profile/2'
     *@param {Any Type} params The parameter you to set for the route
     *@return param value for that parameter.
     **/
    param: function(fragment, params) {
        var matchedRoute;
        _.any(Backbone.history.handlers, function(handler) {
            if (handler.route.test(fragment)) {
                matchedRoute = handler.route;
            }
        });
        if (params !== undefined) {
            this.routeParams[fragment] = params;
        }

        return this.routeParams[fragment];
    },

    /*
     * Called when hash changes to home route
     **/
    onHomeRoute: function() {
        console.log("param =", this.param("home"));
    }

})

Here I have written a custom function "param" for doing the get/set of parameters you want to send.

Now to send a custom parameter you can send it like the following:

var router = new Router();
Backbone.history.start({});
router.navigate("home", {
    params: 'Your data'
});

To retrieve the data in get data inside the callback function you can write code like this:

this.param("home"); //this will return the parameter you set while calling navigate function or else will return null



回答2:

Router.navigate() doesn't pass any data. It sets the url fragment and takes a couple options. See the docs here: http://backbonejs.org/#Router-navigate

My suggestion:

  • Use Router.navigate() to change the URL.
  • Use the Backbone.Events aggregator to trigger (or publish) your event and data.

So say you have a list of movies, and you have a view button. The view button publishes the model it wants shown and changes the URL fragment.

var vent = _.extend( {}, Backbone.Events ); // Create your app specific event aggregator

var ListaCinemaView = Backbone.View.extend({

    ...

    Dettagli : function(){
        vent.trigger('movie:show:request', this.model);

        Backbone.history.navigate( this.model.get('id') );
    }
}

Somewhere else in your app add a handler for movie:view:request.

vent.on('movie:show:request', showMovieDetails);

var showMovieDetails = function(model) { ... }

Lastly, check out MarrionetteJS. It uses the publish/subscribe pattern to handle communication between parts of an app. It's a really nice framework since you basically opt-in to the parts that you want to use. It's very well documented and supported. Also, its creator, Derick Bailey, is very active on Stackoverflow, so you'll get help quick.



标签: backbone.js