/excess-router

Express-style routing for Polymer

Primary LanguageHTML

excess-router

Express-style routing for Polymer

Live demo and docs

Example

<my-app>

  <excess-route
    route="/:topmenu"
    topmenu="{{appMenu}}"
  ></excess-route>
  <excess-route route="/(.*)" redirect_to="/first"></excess-route>

  <iron-pages selected="{{appMenu}}" attr_for_selected="name">
    <first-page name="first"></first-page>
    <second-page name="second"></second-page>
  </iron-pages>

</my-app>

Features

excess-router is a standard full-featured router, implementing routing functionality also found in Angular, React, page.js.

  • two Polymer elments: <excess-route> and <excess-router-config>

  • Javascript library: Excess.RouteManager

  • express-style path matching

  '/users/:id', '/:topmenu/:submenu?', '/(.*)'
  • route aliases:
  <excess-route route="/:topmenu" route-alias="main">
  Excess.RouteManager.navigateTo('@main', {topmenu: '0'});
  • redirection
  <excess-route route="/*" redirect_to="/mainmenu">
  • route transition lifecycle callbacks: willDeactivate, willActivate

  • anchor tag links are routed

  <a href="/#mainmenu"></>
  • multiple routes can be active at once.

    • fine-grained control over matching: route can be active only if no others match
    • see Polymer Starter Kit example below for usage examples.
    • with this secret superpower, complex routing can be done with configuration only
  • configurable

    • '#' hash, or '/' path style paths.
    • hashPrefix
    • manual start
  • lazy display/loading when you use lazy-pages

How to use

<excess-route> binds window's URL to its attributes. Route keys will be bound to <excess-route>'s properties. For example:

<my-app>
  <excess-route route="/users/:userId" user-id="{{appUserId}}">
</my-app>

:userId key match will propagate to excess-route.userId, and my-app.appUserId.

When window.location is #/users/1

  • excess-route.userId be 1
  • my-app.appUserId will be 1
  • setting my-app.appUserId to 999 will cause
    • excess-route.userId to become 999
    • which causes excess-route to call Excess.RouteManager.navigateTo('/users/999')
    • which changes window.location to #/users/999

Once route's keys have been reflected to your app, use Polymer's bindings to connect your route to <iron-pages>, <neon-animated-pages>, <lazy-pages>, or whatever your route uses for navigation.

Not all routing use cases are covered just by using <excess-route>. If your problems become complex, you can drop down into Javascript and use Excess.RouteManager library and use your JS superpowers.

Example

See demo for a fully working example. How would you use this in Polymer Starter Kit?

    <my-app>
      <!-- this route routes the main menu -->
      <excess-route
        route="/:mainmenu/(.*)"
        mainmenu="{{appRoute}}"></excess-route>
      <!-- this wildcard route will redirect to default route if no other routes match-->
      <excess-route
        route="/(.*)"
        redirect-to="/home"
        activation-modifiers="x"></excess-route>
      <paper-menu attr-for-selected="route" selected="{{appRoute}}">
        <a href="#/home" route="home">Home</a>
        <a href="#/users/all" route="users">Users</a>
        <a href="#/contact" route="contact">Contact</a>
      </paper-menu>
      <iron-pages attr-for-selected="route" selected="{{appRoute}}">
        <section route="home">...</section>
        <section route="users">
          <!-- this route manages /users subtree -->
          <excess-route
            route="/users/:userId"
            user-id="{{userId}}"
            active="{{hasUserId}}"></excess-route>
          <template is="dom-if" if="{{!hasUserId}}">
            <!-- if user id is not specified, show a list of users -->
            <section user="all">
              <p>This is the users section</p>
                <a href="#/users/Rob">Rob</a>
            </section>
          </template>
          <template is="dom-if" if="{{hasUserId}}">
            <!-- if user id is specified, show the user -->
            <iron-pages attr-for-selected="user" selected="{{userId}}">
              <section user="Rob">
                User:<span>{{userId}}</span>
              </section>
            </iron-pages>
          </template>
        </section>
      </iron-pages>
    </my-app>

Notes

Why excess-router? Because it uses pathToRegexp, same route parsing library as express, and it has an excess of features.

My routing needs are simple. If you have some interesting ones, and would like to figure out how to use this element for it, give me a shout.

Intially, <excess-route>s could be nested. It more than doubled the code size, and I could not come up with a good use case. I've decided that what I really want is nesting built into the core library.