This question already has answers here:
Backbone.js and pushState
(4 answers)
Closed 3 years ago.
I have defined backbone router:
MyApp.router = new (Backbone.Marionette.Router.extend({
routes: {
"/m/:id": "openMovie",
"m/:id": "openMovie"
},
openMovie: function(id) {...}
});
My html has link like /m/123. When I click this link backbone doesn't trigger openMovie function - browser opens new page. Why doesn't backbone use history api in this case? How can I fix it with backbone or marionette?
Backbone pushState support is opt-in. When you've initialized all your routers, call
Backbone.history.start({pushState: true})
The default behavior is to listen to hashchange events using url #fragments, so if you don't want to use pushState, define you links with a hash url:
and if you want the compatible version:
if (!Backbone.History.started) {
// Enable pushState for compatible browsers
var enablePushState = true;
// Disable for older browsers
var pushState = !!(enablePushState && window.history && window.history.pushState);
Backbone.history.start({ pushState: pushState });
}
>
Related
This should be super basic but I can't get routing working. I should mention that the application is located in a subdirectory called /dist/. Here's my code:
var QuestionRouter = Backbone.Router.extend({
routes: {
"/dist/" : "startTest"
"dist/:id": "getModel"
},
startTest: function(){
console.log('home called')
},
getModel: function(){
app.getModel(id);
}
});
var app = new QuestionView;
var appRouter = new QuestionRouter;
Backbone.history.start({pushState: true});
The URL to trigger this route is:
www.example.com/dist/
www.example.com/dist/12345
Any help would be appreciated.
You'll need to use # (hash symbol).
Backbone routers are used for routing your applications URL's when
using hash tags(#)
This is a quote from a Backbone tutorial: What is a router?
See Backbone's Router documentation
Then your routes would be:
www.example.com/#/dist/
www.example.com/#/dist/12345
You can also use Backbone routes without hashes.
Ok So I was able to work this out:
My route hash should look like this:
routes: {
"" : "startTest",
":id": "getModel"
}
I had to remove pushState: true, with this in place the route wasn't being triggered, not sure why:
Backbone.history.start();
In our app, we actually have two Backbone SPA applications. The first one is for login, registration and other features for unauthenticated users. The URL for this would be something like http://www.example.com/registration#signin. Once you login, you are redirected to our main Backbone app at http://www.example.com/ui#home.
In my main UI app, I am using Backbone.history without pushState. The App file looks something like:
define(function (require) {
var App = new Marionette.Application();
App.addInitializer(function (options) {
...
});
...
App.on('initialize:after', function () {
$(function(){
if (Backbone.history) {
Backbone.history.start({ root: '/ui' });
}
});
$.log("**WebApp**: Marionette app started.");
});
return App;
});
Of course, everything works flawlessly in any browser except IE 9 (and maybe 10, I need to check). In IE 9, all the routing works fine. Clicking links such as http://www.example.com/ui#anotherpage works. However, when the user clicks the Back button in their browser, they are not sent back to the last route fired. Instead, they are sent to http://www.example.com/registration#signin, which is the last page served by Node, our web server. As I click through links, I can see that history.length and Backbone.history.history.length are not updating.
All routes are fired from links/URL's. I'm not using router.navigate() within the code. Here are examples of our Router:
define(function (require) {
var Backbone = require('backbone'),
Marionette = require('marionette');
return Backbone.Marionette.AppRouter.extend({
appRoutes: {
"": "showHome",
"home": "showHome",
"foo": "showFoo"
}
});
});
And Controller:
define(function (require) {
var Backbone = require('backbone'),
Marionette = require('marionette');
return Backbone.Marionette.Controller.extend({
showHome: function () {
require(['webapp','modules/home'], function (WebApp) {
WebApp.module("Home").start();
WebApp.module("Home").controller.showModule();
});
},
showFoo: function () {
require(['webapp', 'modules/foo'], function (WebApp) {
WebApp.module("Foo").start();
WebApp.module("Foo").controller.showModule();
});
}
});
});
UPDATE:
On further research, it turns out the problem is that older versions of IE don't record hash changes in their history. See - Change location.hash and then press Back button - IE behaves differently from other browsers. But I'm still not sure what the workaround for this would be. I'm guessing it would somehow involve manually handling hash change events with a plugin such as jQuery Hashchange and doing... something? Manually setting IE's history? Or crafting a custom history object and using it when we detect a Back button in IE?
I was having the same problem in one of our apps for IE.
Starting backbone history like below works.
Backbone.history.start({
pushState: true,
hashChange: false
});
Update: As mentioned By T Nguyen,
When you set pushState to true, hash URL's no longer trigger routes. Unless you add server-side support for all your Backbone routes, you need to add an event handler on the client side which captures appropriate links and calls .navigate() on the route
We are investigating a migration from Backbone to Angular. Because of our design, we only need to migrate the router. I'd like to understand how wildcard routing works for angular. Here is an example of wildcard routing in Backbone:
app.Router = Backbone.Router.extend({
routes: {
'*filter' : 'setFilter'
},
setFilter: function(params) {
//all traffic ends up here. you can grab the url and go.
var url = this.cdn + "templates/" + params + ".html";
...
}
});
app.router = new app.Router();
Backbone.history.start({pushState: true});
What is the angular equivalent for wildcard routing?
How does angular handle push state? Specifically, does it have a way to utilize /pushstate urls when the browser supports pushstate and then automatically roll back to #pushstate hash urls for IE9-
Thanks.
1) There is not current support for regex in angular routing
2)Angular automatically handle pushstate if it is not available in browser then it will automatically fallback to hash mode# just use below lines
$locationProvider.html5Mode(false);
$locationProvider.hashPrefix('!');
Ok, I think this is something simple, however I am being to stupid to see it. Here is my code in backbone using the backbone boilerplate method
require([
"app",
// Libs
"jquery",
"backbone",
// Modules
"modules/example"
],
function(app, $, Backbone, Example) {
// Defining the application router, you can attach sub routers here.
var Router = Backbone.Router.extend({
routes: {
"": "index",
"item" : 'item'
},
index: function()
{
console.info('Index Function');
var tutorial = new Example.Views.Tutorial();
// Attach the tutorial to the DOM
tutorial.$el.appendTo("#main");
// Render the tutorial.
tutorial.render();
},
item: function()
{
console.info('Item View');
}
});
// Treat the jQuery ready function as the entry point to the application.
// Inside this function, kick-off all initialization, everything up to this
// point should be definitions.
$(function() {
// Define your master router on the application namespace and trigger all
// navigation from this instance.
app.router = new Router();
// Trigger the initial route and enable HTML5 History API support
Backbone.history.start({ pushState: true, root: '/reel' });
});
// All navigation that is relative should be passed through the navigate
// method, to be processed by the router. If the link has a data-bypass
// attribute, bypass the delegation completely.
$(document).on("click", "a:not([data-bypass])", function(evt) {
// Get the anchor href and protcol
var href = $(this).attr("href");
var protocol = this.protocol + "//";
// Ensure the protocol is not part of URL, meaning its relative.
if (href && href.slice(0, protocol.length) !== protocol &&
href.indexOf("javascript:") !== 0) {
// Stop the default event to ensure the link will not cause a page
// refresh.
evt.preventDefault();
// `Backbone.history.navigate` is sufficient for all Routers and will
// trigger the correct events. The Router's internal `navigate` method
// calls this anyways.
Backbone.history.navigate(href, true);
}
});
});
I am running this of a MAMP server and when i type Localhost:8888/reel , I get the example index page that comes with boilerplate. However when I type Localhost:8888/reel/item or Localhost:8888/reel/#item I either get, page can not be found or directed back to my index page.
My question is what am i doing wrong. Do I need to use htaccess? This doesnt seem right. Is there a way using backbone to sort this. Sorry if this is really simple, just cant get my head around it.
the problem may lie with the pushState flag.
With that on the request goes all the way to the server and it sees the full url and responds to it with whatever it would do ...
does it work if you have a
$(function (){
setTimeout(navMe, 2000);
});
function navMe() {
backbone.navigate("item");
}
that way 2 seconds after load it will navigate to item view and you know that its because of the request going to the server and not to backbone.
I am pretty new to backbone js and I am having some problem getting the pushstate functionality of my app to work. Here is an eg of my route:
var TodoRouter = new (Backbone.Router.extend({
routes: {
"": "index",
"item/add": "AddTodoItem",
"list/add": "AddTodoList"
},
AddTodoItem: function() {
//e.preventDefault();
alert("add new item");
},
AddTodoList: function(e) {
//e.preventDefault();
alert("add new list");
},
Start: function(){
//note: my directory structure is localhost/playground/todo/
Backbone.history.start({pushState: true, root: "/playground/todo/"});
},
initalize: function(){
},
index: function(){
var todoListView = new TodoListView({ collection: TodoItemCollection });
}
}));
Here is how I call my route:
$(function() {
TodoRouter.Start();
});
And lastly here is how I call a link:
New List
The problem that I am running into is that when I call the link, the page stays the same, no alert and the browser displays:
http://localhost/playground/todo/#list/add
Now here is the funny part, if I refresh the page, the url become:
http://localhost/playground/todo/list/add
and I get the alert. So I have a feeling I am missing a key point somewhere. Any help would be greatly appreciated!
You have pushState: true and that's why it preferred the slash / instead of hash #
Either change that or remove the hash
You're trying to use Backbone Routes and html5 pushState.
As the backbone documentation said:
"if you have a route of /documents/100, your web server must be able
to serve that page, if the browser visits that URL directly."
So if you want to trigger some functions through uri (localhost/webapp/#about) you just need to use Backbone Routes.
If you want to use Backbone Routes and pushState, you'll need a back-end to answer requests made to your readable url (localhost/webapp/about) and need to use backbone.navigate method to avoid the browser understand <a href="#someRoute"> as a html anchor.
here you can see a complete example
You can't trigger your route, because when pushState:true the href="#route" has the same behavior as a html anchor.