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);?
Related
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).
Trying to get a backbone router to work. Having one of those situations where nothing is happening so its difficult to pinpoint the problem.
Is there a way to find out what the Router is actually receiving so that I can try to pinpoint the problem with my routes?
This is the code so far:
// ROUTER
var TheRouter = Backbone.Router.extend({
// ROUTES
routes: {
"": "main",
"/route1/:key": "route1"
},
// INITIALIZE
initialize: function() {
_.bindAll(this);
},
// ROUTES
main: function(){
alert('main');
},
route1: function(key){
alert(key);
}
});
// Create new router
var theRouter = new TheRouter();
// Start history
Backbone.history.start({pushState: true});
Thanks so much!
You can bind to the route event on the Backbone.history. According to the source code you get all the info going into the router from that event, meaning you should be able to console.log it.
You need to remove the slash from the beginning of your second route.
So the
"/route1/:key": "route1"
line becomes
"route1/:key": "route1"
If you are still getting no feedback, make sure you defined your dependent scripts in the correct order (jquery.js, underscore.js, backbone.js, yourRouter.js).
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();
I have a simple implementation of Backbone.js which goes like this -
$(document).ready(function(){
Workspace = Backbone.Router.extend({
routes: {
"/getAcademics": "academics"
},
academics: function(){
alert("ok");
$("#content").append("<div>Academics</div>");
}
});
var myWorkspace = new Workspace;
});
The link in the body is given as -
Academics
Though the router routes to the link #/getAcademics but it does not execute the function academics. Any clues as how to rectify this. Am I missing something else.
Thanks
After you instantiate your router, and before you attempt to use any of its routes, you need to call Backbone.history.start(). This will setup a listener for hash changes and call the correct route functions when needed.
You can find more information here: http://documentcloud.github.com/backbone/#History