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.
Related
I see a lot of examples with just some router code and that's it. My href in my HTML must start with a "#" so the page doesn't redirect, correct?
So let's say my a tag looks like so:
Login
What should the route look like in the router?
App.Router = Backbone.Router.extend({
routes: {
"login": "loginAction"
},
loginAction: function(){
// do cool stuff
}
});
Does the route above need the hash or any kind of backslash?
Or should my href in my anchor be "/#/login" ?
Also, I've seen this code
Backbone.history.start({
pushState: true
});
What does this mean and what does it do?
Do I use this code after or before I create a new instance of my router?
I have another small hack for you.
First define your links as usual
Login
than before starting the Backbone Router, call this jQuery snippet
$(document).on('click', 'a[href^="/"]', function(e) {
e.preventDefault();
var href = $(e.currentTarget).attr('href');
Backbone.history.navigate(href, { trigger: true });
});
what does this snippet do, is only block redirection of all href, and let the Backbone router take the job for you (without refresh).
var router = new App.Router();
Backbone.history.start({pushState: true}); // Start the Router
In my Backbone app (Rails backend), I am using [Handlebars] Javascript templates (JST's) for rendering my Backbone views. Whenever I do a browser refresh while on one of those URL templates, it jumps back to the root URL. I want it to stay on that current template after page-refresh. I want to do something like this...
getPage: function() {
$(window).on('beforeunload', function(){
var fragment = Backbone.history.fragment;
});
if (fragment === "this_current_template") {
return App.getCurrentTemplatePage(); // render it
} else if (fragment === "") {
return App.getFrontMainPage(); // render it
}
}
getPage is a method in my backbone App object. My fragment variable can't be recognized outside of the $(window) event handler. I can't seem to find a way to persist my previous Backbone.history.fragment in a variable, even if I make fragment global. It's all swept away after refresh. I know about Backbone.history.loadUrl(Backbone.history.fragment);, but I just can't get that to work either. It only seems to work prior to browser refresh.
Is it something I'll have to change in the root route of my backend code? or is there a way to persist the current page using Backbone / JS on page reload? Any help on this would be much appreciated!
First of all you need to create a Router. According to Backbone docs:
var Router = Backbone.Router.extend({
routes: {
"main": "main"
},
main: function() {
// your code here
}
});
After that you only need to init Backbone.history:
Backbone.history.start({});
After that Backbone automatically will try to find appropriate route for your hashbang and fire the appropriate action. In given example if your initial hashbang will be #main then Router.main action will be executed.
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);?
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).
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();