Home Start Get started Build an element 1. Get set up 2. Add local DOM 3. Data binding & properties 4. React to input 5. Theming with custom properties Build an app 1. Get set up 2. Create a new page 3. Add some elements 4. Deploy Polymer Feature overview Quick tour Define elements Register an element Declare properties Instance methods Behaviors Local DOM & styling Local DOM Styling Events Handle and fire events Gesture events Data system Data system concepts Work with object and array data Observers and computed properties Data binding Helper elements Tools Tools overview Polymer CLI Document your elements Test your elements Optimize for production Publish an element Advanced tools Services What's new Release notes 1.0 Migration guide About Polymer 1.0 Resources Community Browser compatibility API Reference Polymer.Base array-selector custom-style dom-bind dom-if dom-repeat dom-template Polymer.Templatizer Global settings 2.0 Preview About Polymer 2.0 Upgrade guide App Toolbox What's in the box? Using the Toolbox App templates Responsive app layout Routing Localization App storage Service worker Serve your app Case study Shop News Elements News What's in the box?
Using the Toolbox
App templates Responsive app layout Routing Localization App storage Service worker Serve your app
Case study
Shop News

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 the app-route package with Bower:

bower install --save PolymerElements/app-route

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>

The route object contains two properties:

  • prefix. The path matched by the previous <app-route> element. For the top-level <app-route> element, prefix is 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'
}

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 its route property. 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 route object is read-write, so you can use two-way data binding or this.set to update the route. Both the route and routeData objects can be manipulated this way. For example:

    this.set('route.path', '/search/');

    Or:

    this.set('routeData.user', 'mary');

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
}