I have the following router:
appRouter = Backbone.Router.extend({
routes: {
'': 'inbox',
'inbox': 'inbox',
'discussions_engagement': 'contacts',
},
inbox: function(page) {
console.log('inbox');
var page = page || 1;
engage.app.hydrateInbox(page, engage.app.showInbox);
},
....
};
When I am on http://[...]/#inbox and I call
appRouter.navigate('inbox', {trigger: true});
the inbox action doesn't fire which is what I want to achieve. Now I have looked at the source of Backbone (https://github.com/documentcloud/backbone/blob/master/backbone.js#L1027) and I see that it doesn't support what I'm trying to do but is there some way of accomplishing this?
I would create an event manager in your engage.app object, like this:
var vent = _.extend({}, Backbone.Events);
Then in your router do this for the inbox route:
vent.trigger('inbox:show', page);
And handle that event in the engage.app object, doing the code there that used to be in the route handler.
Now, instead of calling appRouter.navigate you can trigger that same event.
Also, from that handler, you can call appRouter.navigate('inbox'); without passing true. Now you can get your app to the state you want without trying to force the route.
As far as I can tell... As of Backbone 0.9.10 using appRouter.navigate('inbox', {trigger: true}); works as expected.
Another option is just to call the method
appRouter.inbox();
Related
I have an issue with backbone.js history.
When an user click on a link, I stop the propagation and I would like to call the method matching with the href without changing the location.
$(document).on("click", "a[href^='/']", function(event){
event.preventDefault();
event.stopPropagation();
Router.goToIntraRoute($(event.target).attr("href"));
});
In the backbone router :
var Router = Backbone.Router.extend({
routes: {
"user/:id": "openProfile"
},
// Changes the location
modifyRoute: function(route){
this.navigate(route, {trigger: true, replace: false});
},
// Doesn't change the location
goToIntraRoute: function(route){
// URL modified
this.navigate(route, {trigger: false, replace: false});
}
});
I would like the method goToIntraRoute doesn't modify my url but trigger the method... Can anyone help me?
Assuming that you don't want the new "page" to appear in the history, you could just call the route handler directly. To get you started, here's a simplified example:
goToIntraRoute: function(route){
if (this.routes[route]) {
this.routes[route]();
}
}
To actually use that fragment, you'll need to manage the context (this) appropriately. Also, if your routes include wildcards or regular expressions, then you'll have to explicitly parse those from the parameters since you won't be relying on the router.
In Backbone, is there any way to trigger a route event handler, without changing the URL?
What I mean is that I want to trigger a route handler, but I don't want to change the URL.
Hence, I don't want to use
router.navigate(route, {trigger: true});
as this will cause the URL to change.
The router itself is connected to a function. The simple answer is to call the function straight away, simply bypassing the route handling.
Example
(function( $, Backbone ) {
var exports = window.app = window.app || {},
Router = Backbone.Router.extend({
// Here you declare what the routes are in your router
// and what functionality they should trigger.
routes: {
"help" : "help",
"search/:query" : "search",
"search/:query/p:page": "search"
},
// Declare route functions.
help : function() {},
search: function( query, page ) {}
});
// Export the router.
exports.router = new Router();
// Just a dummy object for calling the router.
var cookieMonster = {
init: function() {
// Do something on init.
// End with calling the route help function.
exports.router.help();
}
};
}(jQuery, Backbone));
cookieMonster.init() would in this case end with a call to the help function in the router.
A tip is to look at Backbone Marionette where you have a Controller which has the function logic seperated from the routes, one of many things that make Marionette awesome.
For what its worth, Marionette routing is explained extensively here: http://samples.leanpub.com/marionette-gentle-introduction-sample.pdf
The strategy that is discussed is separating URL management from application reactions (e.g. switching sub-applications). This means that you're then free to have your app trigger a handler (using a Marionette event) without modifying the URl fragment.
Have you tried Backbone.history.loadUrl(route);?
I'm working with the latest release of Ember JS (RC1), and I have an architectural problem :
I have a very simple use case : a list of users, and a form to add users.
My Router:
App.Router.map(function () {
this.resource('users', function () {
this.route('new');
});
});
My Routes:
App.UsersRoute = Em.Route.extend({
model:function () {
return App.User.findAll();
}
});
My Controller:
App.UsersNewController = Em.ObjectController.extend({
saveUser:function () {
//'content' contains the user
App.User.save(this.content);
// here i want to reload the list of users, but it doesn't work
// The application goes correctly to the url /users
// But doesn't call the 'model' function
this.transitionToRoute('users');
}
});
As I say in the above comment, when I create a new User, I'd like to redirect to the list of users (that part works) AND reload the user list by calling the 'model' method of the route (that part doesn't).
I could write a method in UsersController to reload the list, but then I would have duplication between UsersRoute and UsersController.
Can someone help me on this problem ?
Thanks
P.S. : here a fiddle http://jsfiddle.net/vsxXj/
Ember Documentation on the model hook:
"A hook you can implement to convert the URL into the model for this
route."
So i do not think that this hook is right for this case. I think you should use the setupController hook for this case. Try this:
App.UsersRoute = Em.Route.extend({
setupController(controller){
controller.set("content", App.User.findAll());
}
});
If I navigate to a view by clicking on a link such as 127.0.0.1/#/project/1, the correct view gets displayed. However, if I call this url directly in the browser (or hit refresh), the view won't be displayed. What could be the reason for this behaviour?
The way I set up the Router is as follows:
var AppRouter = Backbone.Router.extend({
routes: { },
initialize:function () { }
});
var app = new AppRouter();
and then in every module (I'm using require.js), a route and handler will be added
app.route("project/:id", "showProject");
Could it be that the routes aren't registered yet and thus the callbacks won't be called?
Make sure that you are calling Backbone.history.start() after all of your routers are loaded/instantiated and routes defined: http://backbonejs.org/#History-start
Alternatively, you could stop the history with Backbone.history.stop(), and start it again. Then the added route(s) will be picked up.
BTW, you can test if the history is currently started with the boolean Backbone.History.started (note the capital 'H' is necessary).
Just wanted to know, what is the proper way of returning to the index in backbone.js? So this is an outline of my code. I have a router, where it creates an instance of a view and passes the current instance of the router.
var AppRouter = Backbone.Router.extend({
callMasterViefw: function(){
MasterView.initialize(this);
},
})
Inside the MasterView, I create an instance of the MasterView and assign the router to it as well. I have a function, called reRouteToIndex, where basically i want to reroute to the index page.
MasterView= Backbone.View.extend({
render: function(){},
reRouteToIndex(){
this.router.navigate("", {trigger: true,replace: true});
},
});
All this works, but the problem is when I redirect to the index I return to something like www.test.com/index.html/#. Where it is important to note the # at the end. I was wondering if there was a way to route to the original path without the # like this www.test.com/index.html?
You could enable pushState in .navigate() (like .navigate({pushState: true, trigger: true}) but you'll need to configure your webserver to work with mod_rewrite (or equivalent).