googlearchive / more-routing

144 stars 30 forks source link

NOTE: This router is not currently actively maintained by the Polymer core team.

Our aim is to create a more integrated product line of components for structuring applications, where each is tightly scoped.

Generally, the PolymerLabs/ organization is used as a testing ground for components - those that will be supported and continue to evolve long-term will be in the PolymerElements/ organization.

If anyone would be interested in evolving this particular component long-term, please let @tjsavage know!

Routing

A composable suite of objects and elements to make routing with web components a breeze.

Rob Dodson has whipped up a great video that can get you started with more-routing:

Moar routing with... more-routing

Or, TL;DR:

<link rel="import" href="https://github.com/googlearchive/more-routing/blob/master/./more-routing/more-routing.html">

<more-routing-config driver="path"></more-routing-config>
<more-route name="user" path="/users/:userId">
  <more-route name="user-bio" path="/bio"></more-route>
</more-route>

<more-route-selector selectedParams="{{params}}">
  <iron-pages>
    <section route="/">
      This is the index.
    </section>

    <section route="/about">
      It's a routing demo!
      <a href="https://github.com/googlearchive/more-routing/blob/master/{{ urlFor('user-bio', {userId: 1}) }}">Read about user 1</a>.
    </section>

    <section route="user">
      <header>Heyo user {{params.userId}}!</header>
      <template if="{{ route('user-bio').active }}">
        All the details about {{params.userId}} that you didn't want to know...
      </template>
    </section>
  </iron-pages>
</more-route-selector>

And finally, check out the demo for a project that makes comprehensive use of the various features in more-routing.

Element API

<more-routing-config>

Defined in more-routing-config.html.

The declarative interface for configuring MoreRouting. Currently, this lets you declare which driver you wish to use (hash or path):

<more-routing-config driver="hash"></more-routing-config>

You should place this as early in the load process for your app as you can. Any routes defined prior to the driver being set will trigger an error.

<more-route>

Defined in more-route.html.

Reference routes by path, and extract their params:

<more-route path="/users/:userId" params="{{user}}"></more-route>

Declare a named route:

<more-route path="/users/:userId" name="user"></more-route>

Reference a named route:

<more-route name="user" params="{{user}}"></more-route>

Route Nesting

Routes can also be nested:

<more-route path="/users/:userId" name="user">
  <more-route path="/bio" name="user-bio"></more-route>
</more-route>

In this example, the route named user-bio will match /users/:userId/bio.

Finally, <more-route> elements can declare a routing context for the element that contains them by setting the context attribute. See the routed elements section for more info.

<more-route-selector>

Defined in more-route-selector.html.

Manages a <iron-selector> (or anything that extends it/looks like one), where each item in the selector have an associated route. The most specific route that is active will be selected.

<more-route-selector>
  <iron-pages>
    <section route="/">The index!</section>
    <section route="user">A user (named route)</section>
    <section route="/about">Another route</section>
  </iron-pages>
</more-route-selector>

By default, more-route-selector will look for the route attribute on any children of the iron-selector (change this via routeAttribute).

It exposes information about the selected route via a few properties:

selectedParams: The params of the selected route.

selectedRoute: The MoreRouting.Route representing the selected route.

selectedPath: The path expression of the selected route.

selectedIndex: The index of the selected route (relative to routes).

Routed Elements

Elements can declare a route to be associated with, which allows <more-route-selector> to be smart and use that as the route it checks against for your element. For example:

<polymer-element name="routed-element">
  <template>
    <more-route path="/my/route" context></more-route>
    I'm a routed element!
  </template>
</polymer-element>
<more-route-selector>
  <iron-pages>
    <section route="/">The index!</section>
    <routed-element></routed-element>
  </iron-pages>
</more-route-selector>

In this example, The <more-route-selector> will choose <routed-element> whenever the path begins with /my/route. Keep it DRY!

Nesting Contexts

Similar to more-route's nesting behavior, any items in the iron-selector also behave as nesting contexts. Any route declared within a routing context is effectively mounted on the context route.

Taking the example element, <routed-element> above; if we were to add the following to its template:

<more-route path="/:tab" params="{{params}}"></more-route>

That route's full path would be /my/route/:tab, because /my/route is the context in which it is nested. This allows you to create custom elements that make use of routes, while not requiring knowledge of the app's route hierarchy. Very handy for composable components!

Note: All items in a <more-route-selector> are treated as routing contexts!

Polymer Helpers

Filters

Defined in polymer-expressions.html.

Several filters (functions) are exposed to templates for your convenience:

route

You can fetch a MoreRouting.Route object via the route filter. Handy for reading params, etc on the fly.

<x-user model="{{ route('user').params }}"></x-user>

Note: The route() helper is unfortunately not aware of the current routing context. Consider using only named routes to avoid confusion!

urlFor

Generates a URL for the specified route and params:

<a href="https://github.com/googlearchive/more-routing/blob/master/{{ urlFor('user', {userId: 1}) }}">User 1</a>

JavaScript API

MoreRouting

Defined in routing.html.

The main entry point into more-routing, exposed as a global JavaScript namespace of MoreRouting. For the most part, all elements and helpers are built on top of it.

MoreRouting manages the current driver, and maintains an identity map of all routes.

MoreRouting.driver

Before you can make use of navigation and URL parsing, a driver must be registered. Simply assign an instance of MoreRouting.Driver to this property.

This is exposed as a declarative element via <more-routing-config driver="...">.

MoreRouting.getRoute

Returns a MoreRouting.Route, by path...

MoreRouting.getRoute('/users/:userId')

...or by name:

MoreRouting.getRoute('user')

Because routes are identity mapped, getRoute guarantees that it will return the same Route object for the same path.

MoreRouting.Route

Defined in route.html.

The embodiment for an individual route. It has various handy properties. Highlights:

active: Whether the route is active (the current URL matches).

params: A map of param keys to their values (matching the :named tokens) within the path.

path: The path expression that this route matches.

Paths

Path expressions begin with a / (to disambiguate them from route names), and are a series of tokens separated by /.

Tokens can be of the form :named, where they named a parameter. Or they can be regular strings, at which point they are static path parts.

Should be familiar from many other routing systems.

MoreRouting.Driver

Defined in driver.html.

Drivers manage how the URL is read, and how to navigate to URLs. There are two built in drivers:

MoreRouting.HashDriver

Defined in hash-driver.html.

Provides hash-based routing, generating URLs like #!/users/1/bio. It has a configurable prefix (after the #). By default, it uses a prefix of !/ (to fit the AJAX-crawling spec).

MoreRouting.PathDriver

Defined in path-driver.html.

Provides true path-based routing (via pushState), generating URLs like /users/1/bio. If your web app is mounted on a path other than /, you can specify that mount point via the prefix.