I want a setup/teardown method to be called before and after a route is fired in my Backbone.js router, respectively. Has anyone created an elegant way of doing this?
_.wrap is not a solution, if You have for example 20 routes you have to wrap them all.
But you can do this with metaprogramming
class Backbone.FlexRouter extends Backbone.Router
route: (route, name, handler) ->
super route, name, ->
@trigger "route:before"
handler()
@trigger "route:after"
UPD: I believe in JS it should be something like this (but I didn't tested it)
var rp = Backbone.Router.prototype
rp.routeWithoutEvents = rp.route
rp.route = function(route, name, handler){
var that = this
this.routeWithoutEvents(route, name, function(){
that.trigger("route:before")
handler()
that.trigger("route:after")
})
}
Have you considered _.wrap?
Here is the simple one, overriding the Backbone.Router itself
(function () {
_.extend(Backbone.Router.prototype, Backbone.Events, {
route: function (route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (!callback) callback = this[name];
Backbone.history.route(route, _.bind(function (fragment) {
var args = this._extractParameters(route, fragment);
if (this.before && _.isFunction(this.before)) {
this.before(fragment);
}
callback && callback.apply(this, args);
this.trigger.apply(this, ['route:' + name].concat(args));
if (this.after && _.isFunction(this.after)) {
this.after(fragment);
}
Backbone.history.trigger('route', this, name, args);
}, this));
return this;
}
});
}).call(this);
Focus on the lines
if (this.before && _.isFunction(this.before)) {
this.before(fragment);
}
AND
if (this.after && _.isFunction(this.after)) {
this.after(fragment);
}
You can modify the lines according to your needs
And here is the client code using the new Backbone.Router class
var appRouter = Backbone.Router.extend({
routes: {},
before: function(){
//your code here
return true;
}
});
Alexey's answer is almost right, but there are a few subtle things that are missing.
class ApplicationRouter extends Backbone.Router
route: (route, name, callback = null) ->
callback = @[name] if ! callback
super route, name, ->
@trigger 'route:before'
result = callback && callback.apply(@, arguments)
@trigger 'route:after'
return result
This plugin does what you want. It works with 0.5.3. I'm not certain if it works with 0.9.1 yet or not.
https://github.com/angelo0000/backbone_filters
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With