My view should be destroyed after the current route position is left.
So in this schematic example the login view should be destroyed after the user entered his credentials:
I tried to solve this by using Backbone.Router
events:
var Router = Backbone.Router.extend({
initialize: function () {
Backbone.history.start();
},
routes: {
"sample" : "sample"
},
sample: function(){
// Build view
var demoView = $("<div/>")
.appendTo(document.body)
.text("I am lost!");
// Destroy view
this.once('route', function(){
demoView.remove();
});
},
});
Unfortunately this does not work as the route events are raised after the routes are executed:
/
Is there a solution to destroy views after leaving the route position?
Do I have to hack a new event into Backbone.js?
My view should be destroyed after the current route position is left.
So in this schematic example the login view should be destroyed after the user entered his credentials:
I tried to solve this by using Backbone.Router
events:
var Router = Backbone.Router.extend({
initialize: function () {
Backbone.history.start();
},
routes: {
"sample" : "sample"
},
sample: function(){
// Build view
var demoView = $("<div/>")
.appendTo(document.body)
.text("I am lost!");
// Destroy view
this.once('route', function(){
demoView.remove();
});
},
});
Unfortunately this does not work as the route events are raised after the routes are executed:
http://jsfiddle/hcuX9/
Is there a solution to destroy views after leaving the route position?
Do I have to hack a new event into Backbone.js?
Share Improve this question edited Mar 29, 2013 at 20:31 jantimon asked Mar 29, 2013 at 19:06 jantimonjantimon 38.2k23 gold badges126 silver badges193 bronze badges3 Answers
Reset to default 3What I use to do is to have an App.current
variable pointing to the current view being rendered.
At the top of each route (or the relevant ones in your case), I remove the current view from App.current
and then assign it the new view:
someRoute: function() {
if(App.current && App.current.remove) App.current.remove();
// Asign a new current page
App.current = new SomeView();
...
}
That way I only let one view live per route, getting rid of problems like yours.
If you don't like to be checking for App.current
and invoking the remove method at the top of every route, you can listen for Backbone.history route event and injecting that logic there:
Backbone.history.on('route', function() {
if(App.current && App.current.remove) App.current.remove();
});
I think you are stuck with your hack, unless you can adapt .listenTo to your needs - then you will need to fire a custom event with .trigger anywhere you have a route change, which might not be possible. Note that this functionality has been requested (and denied) before in backbone:
https://github./documentcloud/backbone/pull/494
See that pull request for other patches that try to do the same thing you are doing.
Here, we're using on
and off
to listen for route events ing in instead of once
because we can't rely on a single event not being the current route. When we receive a route even that is not our current route, we can destroy the view and remove the listener:
// Destroy view
var self = this;
var onRoute = function(route, params){
if(route !== 'sample'){
demoView.remove();
self.off('route', onRoute);
}
};
this.on('route', onRoute);
I've modified your test fiddle here: http://jsfiddle/rgthree/hcuX9/3/
Another option, as your fiddle (not in your question) navigates directly to another view. This causes the other route's event to fire after the sample2 route. Because of this the above will remove the view. Now, it's much more plete. A hackier way you could handle it is to simply defer the once
in a setTimeout
so it doesn't listen until after the current route has been fired:
// Destroy view
var self = this;
setTimeout(function(){
self.once('route', function(){
demoView.remove();
});
}, 0);
You can see your fiddle with this method here: http://jsfiddle/rgthree/hcuX9/4/