We're using Backbone.Router
in a pushstate-only mode, so all our client routes are hash-less.
However, we're facing a difficulty with implementing modal views in our app.
The challenge is the following:
In other words, we want modal views to be represented in history.
Our first attempt was to use URL like /login
for login modal and handle them specifically in route
handler. When we're on /otherpage
, opening modal would navigate to /login
, and, when modal is closed, navigate again to /otherpage
.
However, this has a very major problem: URL like /login
doesn't “know” over which view it should be drawn, so we have to redraw everything when pressing Back and Forward.
This actually makes sense: Login modal over Home screen should have different URL from Login modal over Other Page.
My second thought was that maybe we can use hashes for indicating current modal view:
/
/#login
/otherpage
/otherpage#login
This makes the routing handler simple:
This also fits with the idea of hash being a “fragment” of the visible document. (Yes, apps are not documents, bla bla bla. We still want them to be addressable.)
Are there any inherent problems in this approach?
Is there a better approach satisfying our conditions?
If I understand your problem correctly, I don't believe you need a hash and I do believe you can implement the modal by simply adding more routes. If you need to support a login modal over other existing routes, simply add another route that adds login to the end. Here would be an example:
var Login = Backbone.Model.extend({
closeLogin: function () {
this.set({ open: false }, { silent: true });
this.trigger('loginClosed');
}
});
var LoginView = Backbone.View.extend({
el: '#loginModal',
initialize: function () {
this.listenTo(this.model, 'loginClosed', this.closeLogin);
},
closeLogin: function () {
// do whatever you would normally do to close the modal
}
});
var Router = Backbone.Router.extend({
routes: {
'/login': 'defaultRouteLogin',
'': 'defaultRoute',
'otherpage/login': 'otherPageRouteLogin',
'otherpage': 'otherPageRoute'
},
defaultRoute: function () {
// defaultRoute behaviors
this.login.closeLogin();
},
defaultRouteLogin: function () {
// defaultRoute behavior
// instantiate login modal
},
otherPageRoute: function () {
// otherPageRoute behavior
this.login.closeLogin();
},
otherPageRouteLogin: function () {
// otherPageRoute behavior
// instantiate login modal
},
initialize: function () {
this.login = new Login();
this.loginView = new LoginView({ model: this.login });
}
});
To support back-button behavior, use a method that closes your login modal on every route where you could open your modal. Be sure to order the routes correctly.
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