I've got a very simple setup of laravel 4 with 1 controller for trips.
Now another simple setup of Backbone with a Router and routes to regular routes like trips, trips/create. I want to use pushState: true to have nice URL but I can't seem to get it to work. When I try to reach the URLs it sends me to the page served by the server with my json data.
However, if I type: www.mysite.com/#trips I am "redirected" to www.mysite.com/trips and then my method for this specific route triggers.
Here's my Router:
App.Router = Backbone.Router.extend({
routes: {
'': 'index',
'trips': 'trips',
'trips/create': 'newTrip',
'trips/:id': 'showTrip'
},
index: function(){
},
trips: function(){
console.log('All trips') ;
},
newTrip: function(){
console.log('New trip') ;
},
showTrip: function(id){
console.log('trips id:' + id) ;
}
});
This is probably caused by the Backbone router not being able to match the URL to your Backbone routes. To debug, add this to your routes:
'*actions': 'defaultAction'
Then in the router add:
defaultAction: function(path) {
console.log('Route "' + path + '" not defined, redirecting to homepage!');
}
You will probably see that the path is different from anything in your routes. To fix this, you need to tell Backbone the root of your paths. You do this while activating pushstates.
Backbone.history.start({
pushState: true,
root: 'http://mydomain.com/myapplication/'
});
Hope this helps.
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();
I have to serve up my backbone app on the "/b" route and am having trouble hooking in my router. It works fine if I just showView a view, but my route controller functions are not firing when I hook in my router, any thoughts?
router:
define('appRouter', ['marionette', 'rootView', 'changePasswordView'], function(Marionette, rootView, changePasswordView) {
return Marionette.AppRouter.extend({
routes: {
'/b/change-password': 'showChangePassword',
'/b': 'showAccountSettings'
},
showChangePassword: function() {
this.showView(new changePasswordView());
},
showAccountSettings: function() {
this.showView(new rootView());
}
});
});
application onStart (which is confirmed firing):
var Application = Marionette.Application.extend({
...
onStart: function(options) {
console.log('on start');
var router = new appRouter(options);
/** Starts the URL handling framework */
if( ! Backbone.History.started) Backbone.history.start();
router.initialize();
},
...
});
When I visit http://localhost:8080/b (which is for all intensive purposes my index) it renders a blank page.
Default routes in Backbone are hash-based. Link to Your /b route should look like http://localhost:8080/#/b.
If You don't need hash-based links, start history with pushState: true.
Backbone.history.start({pushState: true});
EDIT:
If You serve app on /b path, then You have wrong defined routes. Routes must be defined relative to /b:
routes: {
'change-password': 'showChangePassword',
'': 'showAccountSettings'
},
And access:
http://localhost:8080/b' -showAccountSettings`
http://localhost:8080/b#change-password' -showChangePassword`
I know this is a beginner question, but I read the doc, some tutorials, and I still have a hard time making it work.
I have a simple php rest webservice, you can see the declared urls:
$app->get('/todos', 'getTodos');
$app->post('/todo/add', 'addTodo');
$app->put('/todo/update/:id', 'updateTodo');
$app->delete('/todo/delete/:id','deleteTodo');
Here is my backbone router:
var app.myRouteur = Backbone.Router.extend({
routes: {
"todos": "get",
"todo/add": "add",
"todo/update/:id": "update",
"todo/delete/:id" "delete"
},
get: function() {
alert('get route triggered');
},
add: function() {
},
update: function(id) {
},
delete: function(id) {
}
});
The router is instanciated as such:
var app = app || {};
var ENTER_KEY = 13;
$(function() {
new app.myRouteur();
Backbone.history.start({pushState: true, root: "/api/index.php/"});
new app.AppView();
});
My question is: what should I do so that the models automatically use those routes to communicate with the webservice?
Is this router supposed to define the webservice's urls or only backbone internal urls (and then webservice's urls should be declared in the model)?
I'm a bit lost and confused... not knowing what do to with this router...
1- The Router's routes are here just to organize your application and centerlize the workflow between you views. You can access them by tags or using Backbone.History.navigate() ...
2- The responsables of accessing your webservices are models with urlRoot and collections with url
I have three questions about routing in Backbone.js / Marionette.js :
1) How can I get a list of all the routes my application's routers have registered ?
For example for Express.js (in Node.js) it would be app.routes.
I'm trying to do the same with Backbone.js / Marionette.js but couldn't find any property or method that did this.
2) I want to clean-up my URLs and remove the hashtag "#" in front of them, I know that they trigger the Routers so how can I manage to do this ?
I found the following script that prototypes the Backbone router, but it's more of a hack than a stable solution : Simple backbone routing without hash URLs
3) Is is possible to have sub-routers in Backbone.js / Marionette.js ?
What I mean by sub-router is a router which only handles a part of a url, e.g :
var AppRouter = Backbone.Router.extend({
routes: {
'articles' : 'MyArticleRouter'
}
});
var MyArticleRouter = Backbone.Router.extend({
routes: {
'science' : 'someMethod',
'literrature' : 'someOtherMethod'
}
});
This would categorise my URLs a little bit more by letting me define the main routes in AppRouter and all the subroutes (part after the second slash "/") in category-specific sub-routers.
So for the following URL : "hostname/articles/science", the routing process would look something like this :
1) pass "/articles/science" to AppRouter
2) AppRouter splits the URI and takes the "/articles" part
3) AppRouter finds the registered "/articles" route
4) AppRouter recognises that MyArticleRouter is bound to that URI element
5) AppRouter forwards the routing to that router and only passes the "/science" element as a route
6) MyArticleRouter routes "/science" to the someMethod() and runs it
Thank you in advance !
Answer for #1:
All the routes are registered in Backbone.history.handlers.
Answer for #2:
You can add a handler to every link in your site:
var application = new Backbone.Marionette.Application();
application.addInitializer(function(options) {
// Add class to target a browser, not as standalone app.
if(window.navigator.standalone != true) {
$('body').addClass('no-standalone');
}
// Prevent internal links from causing a page refresh.
$(document).on('click', 'a', function(event) {
var fragment = Backbone.history.getFragment($(this).attr('href'));
var matched = _.any(Backbone.history.handlers, function(handler) {
return handler.route.test(fragment);
});
if (matched) {
event.preventDefault();
Backbone.history.navigate(fragment, { trigger: true });
}
});
});
Of course make sure you use pushState:
if (!Backbone.history.started) {
Backbone.history.start({ pushState: true });
}
That last snippet must be run after you have initialized all your routers.
Answer for #3:
This may work a little to split your routes:
define([
'backbone',
'underscore',
'routers/dashboard',
'routers/anotherroute1',
'routers/anotherroute2'
],
function(Backbone, _, DashboardRouter, AnotherRoute1, AnotherRoute2) {
'use strict';
var application = new Backbone.Marionette.Application();
application.addInitializer(function () {
_.each([DashboardRouter, AnotherRoute1, AnotherRoute2], function(router) {
new router();
});
if (!Backbone.history.started) {
Backbone.history.start({ pushState: true });
}
});
return application;
});
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.