The routing elements are prerelease. APIs may be subject to change.
For client-site routing, App Toolbox uses the
<app-route> element to provide
modular routing. Modular routing means that instead of having a central repository for all your
application's routes, individual components manage some portion of the route, and delegate the rest
to other components.
Why modular routing? For background on <app-route> and modular routing, see
Encapsulated routing with elements.
Install app-route
Install the app-route package with Bower:
bower install --save PolymerElements/app-route
Add routing
Your first task is to decide how your app's routes map to elements. For example, if you have an application with several main views:
| View | Route |
|---|---|
| User profile view | /profile/:user_id |
| Message list | /messages |
| Message view | /detail/:message_id |
You might have a main application element and a separate view component for each tab. The application element manages the top-level route, selects one of the views to display, and delegates the rest of the route to the active view. The app element's template might include markup like this:
<!-- app-location binds to the app's URL -->
<app-location route="{{route}}"></app-location>
<!-- this app-route manages the top-level routes -->
<app-route
route="{{route}}"
pattern="/:view"
data="{{routeData}}"
tail="{{subroute}}"></app-route>
The <app-location> element is simply a proxy for window.location that provides two-way data
binding. A single <app-location> element binds the top-level <app-route> element to the state of
the URL bar.
The <app-route> element matches the current route against a pattern (where :view represents
a parameter). If the pattern matches, the route is active and any URL parameters are added to the
data object. In this case, the path /profile/tina matches the top-level route, setting
routeData.view to profile. The remainder of the route (/tina) forms the tail.
Based on the route, the app can use <iron-pages> to select a view to display:
<!-- iron-pages selects the view based on the active route -->
<iron-pages selected="[[routeData.view]]" attr-for-selected="name">
<my-profile-view name="profile" route="{{subroute}}"></my-profile-view>
<my-message-list-view name="messages" route="{{subroute}}"></my-message-list-view>
<my-detail-view name="detail" route="{{subroute}}"></my-detail-view>
</iron-pages>
If the current URL is /profile/tina, the <my-profile-view> element is displayed, with its
route set to /tina. This view might embed its own <app-route> to process the route: for example,
to load the user's data:
<app-route
route="{{route}}"
pattern="/:user_id"
data="{{routeData}}"></app-route>
<iron-ajax url="{{_profileUrlForUser(routeData.user_id)}}
on-response="handleResponse" auto>
Route objects
The route object contains two properties:
prefix. The path matched by the previous<app-route>element. For the top-level<app-route>element,prefixis always the empty string.path. The path this route object is matching against.
The tail object is also a route object, representing the route to pass to the
next <app-route> in line.
For example, if the current URL is /users/bob/messages and the top-level
<app-route> has the pattern `/users/:user':
The route object is:
{
prefix: '',
path: '/users/bob/messages'
}
The tail object is:
{
prefix: '/users/bob',
path: '/messages'
}
And the routeData object is:
{
user: 'bob'
}
Change routes
When using <app-route>, there are two ways to change the current URL.
-
Links. When you click a link,
<app-location>intercepts the navigation event and updates itsrouteproperty. Using links for your primary navigation is a good idea because they help search indexers understand the structure of your application. -
Updating the route. The
routeobject is read-write, so you can use two-way data binding orthis.setto update the route. Both therouteandrouteDataobjects can be manipulated this way. For example:this.set('route.path', '/search/');Or:
this.set('routeData.user', 'mary');
Take action on route changes
Previous sections showed data binding to routes and route data, but sometimes you need to run code when the route changes. Using observers, it's simple to react to changes to the route or data:
observers: [
'_routeChanged(route.*)',
'_viewChanged(routeData.view)'
],
_routeChanged: function(changeRecord) {
if (changeRecord.path === 'path') {
console.log('Path changed!');
}
},
_viewChanged: function(view) {
// load data for view
}