radiant-router
v0.11.0
Published
A router for Polymer that syncs the URL to a JavaScript object
Downloads
7
Maintainers
Readme
Radiant Router
The <radiant-router>
is a custom element which synchronizes a URL to a JavaScript object and vice versa. It supports query parameters and path capturing.
Installation
NPM (Polymer 3):
npm install radiant-router
Bower (Polymer 1 and 2):
bower install --save MajorBreakfast/radiant-router
Demo
This router is used in production in the Wolf Service App (Spare parts catalog app for the heating, air handling and ventilation systems supplier Wolf GmbH).
How It Works
When the url
property changes:
URL -----(1)---> routing routeState
<----(2)---- system ----(2)---->
When the routeState
object changes:
routing <---(1)----- routeState
URL <----(2)---- system ----(2)---->
- The routing system connects the url with the
routeState
bidirectionally. - The
url
property is meant to be synced to the URL bar, e.g. using<iron-location>
. The routing system keeps the URL in a consitent state, this means that after it detects changes, it might further change the URL, e.g. to remove a trailing slash. - The
routeState
property is an object which is meant to be manipulated by the app. The routing system keeps therouteState
object in a consistent state, this means that after it detects changes, it might further change therouteState
object, e.g. to remove unknown properties. You can see in the example in the next section how therouteState
object looks like.
How To Use
This section shows you how to use the <radiant-router>
.
Polymer 3:
import { Element } from '../@polymer/polymer/polymer-element.js'
import '../@polymer/iron-location/iron-location.js'
import { RadiantRoute } from '../radiant-router/radiant-router.js'
class MyApp extends Element {
static get template () {
return `
<iron-location hash="{{url}}"></iron-location>
<radiant-router url="{{url}}"
route-state="{{routeState}}"
root-route="[[rootRoute]]"></radiant-router>
`
}
static get is () { return 'my-app' }
static get properties () {
return {
rootRoute: {
type: Object,
value: function () {
return new RadiantRoute('')
.add(new RadiantRoute('home'))
.add(new RadiantRoute('about')
.add(new RadiantRoute('terms-of-use'))
.add(new RadiantRoute('imprint'))
)
.add(new RadiantRoute('catalog')
.capturePath()
.booleanQueryParam({ variableName: 'isSearchShown',
queryParamName: 'search' })
.stringQueryParam({ variableName: 'searchTerm',
queryParamName: 'search-term' })
)
}
}
}
}
}
customElements.define(RadiantRouter.is, RadiantRouter)
Polymer 1 and 2:
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-location/iron-location.html">
<link rel="import" href="../bower_components/radiant-router/radiant-router.html">
<dom-module id="my-app">
<template>
<iron-location hash="{{url}}"></iron-location>
<radiant-router url="{{url}}"
route-state="{{routeState}}"
root-route="[[rootRoute]]"></radiant-router>
</template>
<script>
Polymer({
is: 'my-app',
properties: {
rootRoute: {
type: Object,
value: function () {
return new RadiantRoute('')
.add(new RadiantRoute('home'))
.add(new RadiantRoute('about')
.add(new RadiantRoute('terms-of-use'))
.add(new RadiantRoute('imprint'))
)
.add(new RadiantRoute('catalog')
.capturePath()
.booleanQueryParam({ variableName: 'isSearchShown',
queryParamName: 'search' })
.stringQueryParam({ variableName: 'searchTerm',
queryParamName: 'search-term' })
)
}
}
}
})
</script>
</dom-module>
<iron-location>
is used to sync the url string to the url bar of the browser.
The routeState
object looks like this:
{
activeChild: 'about',
queryParams: {},
children: {
home: { activeChild: null, queryParams: {}, children: {} },
about: {
activeChild: null,
queryParams: {},
children: {
'terms-of-use': { activeChild: null, queryParams: {}, children: {} },
imprint: { activeChild: null, queryParams: {}, children: {} }
}
},
catalog: {
activeChild: null,
queryParams: { isSearchShown: false, searchTerm: 'My query' },
children: {},
path: ''
}
}
}
You can freely modify the routeState
object in your application. You may:
- Set the
activeChild
properties to change which routes are active. - Change properties of the
queryParams
objects. - Change the
path
property of the'catalog'
route (which has path capturing enabled)
All changes will be reflected back to the URL.
Tips and Tricks
How to Redirect
Redirecting can be implemented by setting up an observer to the routeState
object.
The following code redirects from any unknown route to the 'home'
route. Simply checking whether the activeChild
property is null
suffices, because the router automatically sets it to null
whenever it encounters an unknown route.
static get observers () {
return ['_onActiveChildRouteChange(routeState.activeChild)']
}
_onActiveChildRouteChange (routeName) {
if (!routeName) { // null? => Redirect to home
Promise.resolve().then(() => { this.set('routeState.activeChild', 'home') })
}
}
Polymer expects that _onActiveChildRouteChange()
doesn't change the value while it runs. Therefore the desired modification is done asynchronously using a Promise
(Promises have microtask timing, i.e. the browser will not rerender in the meantime). More about Polymer's observers in the documentation chapter about observers.