Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/marionettejs/marionette.approuter

Extends the Backbone.Router to make it easier to construct a large number of routes for your app.
https://github.com/marionettejs/marionette.approuter

Last synced: about 2 months ago
JSON representation

Extends the Backbone.Router to make it easier to construct a large number of routes for your app.

Awesome Lists containing this project

README

        

# Marionette.AppRouter

This library was extracted from Marionette v3.

The Marionette `AppRouter` extends the [`Backbone.Router`][backbone-router] to
make it easier to construct a large number of routes for your app. This is
particularly useful if you want to build a large single-page app while keeping
your router's core logic readable.

## Documentation Index

* [Using the AppRouter](#using-the-approuter)
* [Configure Routes](#configure-routes)
* [Configure Routes In Constructor](#configure-routes-in-constructor)
* [Add Routes At Runtime](#add-routes-at-runtime)
* [Specify A Controller](#specify-a-controller)
* [Using Marionette.Object](#using-marionetteobject)
* [Multiple Routers](#multiple-routers)
* [Backbone History](#backbone-history)
* [Handling Route Changes](#handling-route-changes)

## Using the AppRouter

The Marionette AppRouter is typically used to set up your app when the user
loads a specific endpoint directly. Typically, in a single-page app, users will
expect to be able to easily navigate back to a section of the application by
bookmarking a URL and loading it directly. Let's look at a concrete example:

```javascript
var AppRouter = require('marionette.approuter');

var EmailController = {
showEmail: function(email) {
// Look up the email and display it in our main layout
}
};

var EmailRouter = AppRouter.extend({
controller: EmailController,

appRoutes: {
'emails/:email': 'showEmail'
}
});
```

Assuming our application is served from the root, whenever the user accesses
`http://ourapplication.com/#emails/email-subject-line-123`, the method
`showEmail` will be called with `email-subject-line-123` as its argument. This
will be covered in more detail below.

## Configure Routes

The AppRouter uses the `appRoutes` option to define how we respond to routes
being accessed. To define routes, set the route as your key and the method to
call as a string referencing a method on your controller. For more information
on route definitions, see the [Backbone documentation][#backbone-routes].

The major difference between `appRoutes` and `routes` is that we provide
callbacks on a controller instead of directly on the router itself. This allows
you to define a simpler router and keep your controller logic closer to the
modules it interacts directly with:

```javascript
var AppRouter = require('marionette.approuter');
var EmailController = require('./emails/controller/email');

var MyRouter = AppRouter.extend({
controller: EmailController,

// "someMethod" must exist at controller.someMethod
appRoutes: {
'email': 'listEmails',
'email/:email': 'showEmail'
}
});
```

As the `AppRouter` extends `Backbone.Router`, you can also define a `routes`
attribute whose callbacks must be present on the `AppRouter`:

```javascript
var AppRouter = require('marionette.approuter');

var MyRouter = AppRouter.extend({
routes: {
'email/:email': 'showEmail'
},

showEmail: function(email) {
// show the email
}
})
```

See the [Backbone documentation][backbone-routes] for more information about
defining `routes`.

### Configure Routes In Constructor

If you want more control when managing your routes, you can define your routes
[on router instantiation][basics-instantiation]:

```javascript
var AppRouter = require('marionette.approuter');
var EmailController = require('./emails/controllers/email');

var MyRouter = new AppRouter({
controller: EmailController,
appRoutes: {
'email/': 'listEmails',
'email/:email': 'showEmail'
}
});
```

### Add Routes At Runtime

In addition to setting the `appRoutes` for an AppRouter, you can add app routes
at runtime, to an instance of a router. This is done with the `appRoute()`
method call. It works the same as the built-in `router.route()` call from
Backbone's Router, but has all the same semantics and behavior of the
`appRoutes` configuration.

```javascript
var AppRouter = require('marionette.approuter');

var MyRouter = AppRouter.extend({});

var router = new MyRouter();
router.appRoute("/foo", "fooThat");
```

Also you can specify a controller with the multiple routes at runtime with the
`processAppRoutes` method. This will preserve the existing controller as well:

```javascript
var AppRouter = require('marionette.approuter');

var MyRouter = AppRouter.extend({});

var router = new MyRouter();
router.processAppRoutes(myController, {
"foo": "doFoo",
"bar/:id": "doBar"
});
```

## Specify A Controller

App routers can only use one `controller` object. You can either specify this
directly in the router definition:

```javascript
var AppRouter = require('marionette.approuter');

var someController = {
someMethod: function(){ /*...*/ }
};

AppRouter.extend({
controller: someController
});
```

The object that is used as the `controller` has no requirements, other than it
will contain the methods that you specified in the `appRoutes`.

### Using Marionette.Object

A controller can also be an instance of
[`Marionette.Object`](https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.object.md) - this is useful for cases where
you want to access the helper tools of the Object API and pass through
information on instantiation.

## Multiple Routers

Marionette allows you to run multiple AppRouters in a single application. It's
recommended that you break your routing into multiple sections, each with its
own router and/or controller setting up the views for their own components. This
will make it much easier to find and manage your route-handling logic as your
application grows in complexity.

## Backbone History

The [Backbone History API][backbone-history] monitors the browser's location bar
and triggers route changes on your app routers. It also provides a set of
methods to change the contents of the location bar manually when you want to
expose functionality to your user via a URL:

```javascript
var Bb = require('backbone');
var Mn = require('backbone.marionette');

var EmailView = require('./email/views/email');

var EmailList = Mn.View.extend({
regions: {
layout: '.layout-hook'
},

showEmail: function(model) {
this.showChildView('layout', new EmailView({model: model}));
Bb.history.navigate('email/' + model.id);
}
});
```

As stated in the Backbone documentation, `navigate` takes an `options` argument
that lets you `trigger` on route change. We recommend against using this as it
tends to cause side-effects like making it hard to ensure the route is only
navigated to once, or unintentionally firing different route changes.

## Handling Route Changes

When the user navigates to a new route in your application that matches a route
in your `AppRouter`, the `route` event will be fired. Listening to this will let
you perform extra custom behavior:

```javascript
var AppRouter = require('marionette.approuter');
var Controller = require('./email/controller');

var MyRouter = AppRouter.extend({
controller: Controller,

appRoutes: {
'emails/:email': 'showEmail'
},

onRoute: function(name, path, args) {
console.log('User navigated to ' + path);
}
});
```

This event handler takes three arguments:

1. `name` - Name of the route
2. `path` - Path that triggered this event
3. `args` - Arguments passed into the route

[backbone-history]: http://backbonejs.org/#History
[backbone-router]: http://backbonejs.org/#Router
[backbone-routes]: http://backbonejs.org/#Router-routes