S
Alla inlägg

BACKBONE- ROUTERS

  • development
  • javascript
  • backbone.js

Defined routers should always contain at least one route and a function to map the particular route to. In the example below, we are going to define a route that is always called.

Optional Routes

Search route with query and optional page parameter is an optional route.

var TodoRouter = new (Backbone.Router.extend({
  routes: {
    'search/:query': 'search',
    'search/:query/p:page': 'search',
  },
  search: function (query, page) {
    page = page || 0;
    console.log(query);
    console.log(page);
  },
}))();

Results:

TodoRouter.navigate('search/milk', { trigger: true });

This will print "milk", 0

TodoRouter.navigate('search/milk/p2', { trigger: true });

This will print "milk", 2

Note the duplicate routes are highlighted. We can resolve this issue with an optional route:

var TodoRouter = new (Backbone.Router.extend({
  routes: {
    'search/:query /p:page ': 'search',
  },
  search: function (query, page) {
    page = page || 0;
    console.log(query);
    console.log(page);
  },
}))();

What if we want to match ‘search/milk/p2/’?

var TodoRouter = new (Backbone.Router.extend({
  routes: {
    'search/:query (/p:page)(/) ': 'search',
  },
  search: function (query, page) {
    page = page || 0;
    console.log(query);
    console.log(page);
  },
}))();

We can use an optional trailing slash (/)

URI with Spaces

What if the URI you provide has encoded spaces?

To doRouter.navigate('search/Hello%20World/p2', {trigger: true})

You will get the following result, which is not decoded:

"Hello%20World", 2

var TodoRouter = new (Backbone.Router.extend({
  routes: {
    'search/:query (/p:page)(/) ': 'search',
  },
  search: function (query, page) {
    page = page || 0;
    query = decodeURIComponent(query);
    console.log(query);
    console.log(page);
  },
}))();

The result will be decoded:

"Hello World", 2

Regex in Routes

Say we want to restrict parameter to numeric input, let's see how can achieve this:

var TodoRouter = new (Backbone.Router.extend({
  routes: {
    'todos/:id': 'show',
  },
  show: function (id) {
    console.log('id = ' + id);
  },
}))();

TodoRouter.navigate('todos/2', {trigger: true})

Result: id = 2

TodoRouter.navigate('todos/notanid', {trigger: true})

Result id = notanid

So this shouldn’t trigger show.

var TodoRouter = new (Backbone.Router.extend({
  show: function (id) {
    console.log('id = ' + id);
  },
}))();

TodoRouter.route(/^todos\/(\d+)$/, 'show');

Here each Regex Capture Group becomes a param.

TodoRouter.navigate('todos/2', { trigger: true }); // id = 2`
TodoRouter.navigate('todos/notanid', { trigger: true });

This doesn't trigger show.

var TodoRouter = new (Backbone.Router.extend({
  initialize: function () {
    this.route(/^todos\/(\d+)$/, 'show');
  },
  show: function (id) {
    console.log('id = ' + id);
  },
}))();

This keeps routes inside the router.

Advanced Regex Routes

Let's examine this advanced route formation:

/^search\/(\w+)(?:\/p(\d+))?\/?$/ --> 'search/:query(/p:page)'

Advanced Regex Routes

This router matches:

'search/milk';
'search/milk/p2';
'search/milk/p2/';

But it doesn't match the following:

'searches/milk';
'search/milk/p2/p1';
'search/milk/2';

Catch-all Routes

Alert user when no route matches:

var TodoRouter = Backbone.Router.extend({
  routes: {
    '*path': 'notFound',
  },
  notFound: function (path) {
    alert('Sorry! There is no content here.');
  },
});

TodoRouter.navigate('nothinghere', { trigger: true });

This will result in:

Catch-all Routes

File Path Route

Accept a file path and get its parts

var TodoRouter = new (Backbone.Router.extend({
  routes: {
    'file/*path': 'file',
  },
  file: function (path) {
    var parts = path.split('/');
    console.log(parts);
  },
}))();

TodoRouter.navigate('file/this/is/a/file.txt', { trigger: true });

Result:

[" this", "is", "a", "file.txt"]

If you want to learn about more follow my other articles on Backbone here: