Built In Routing
Closed this issue · 1 comments
Here's the gist:
https://gist.github.com/pickle-ts/9db6a3d9da292fafbc2671bf14742df7
Design:
Client side routing is modeled as a two-way mapping the path of the browser's current url and component state. So if the url changes, it updates the component state, and vice-versa. The component's routing state is maintained by an instance of 'Router', which merely has a possible current child name. That child name maps to part of a path, where each part is separated by forward slashes. Nested routes map to nested components, making routing composable.
Usage:
Here's a Wizard
component that implements IRoute
as follows:
class Wizard extends Component implements IRoute
{
@Exclude() routeName = "wizard"
@Exclude() router: Router = new Router (this)
@Type(() => Wizard) page1 = new WizardPage1()
@Type(() => Wizard) page2 = new WizardPage2()
childRoute (name: string) {
return this[name] as IRoute
}
}
Every routable component needs a name, and a field holding the router. These are excluded from serialization, because the ultimate source of truth for the state is the browser's url. If the router has child components that also implement IRoute, then the router will maintain the current child name. The parent component must implementchildRoute
in order to map the parent to the child.
Here's the implement of a child route:
class WizardPage1 extends Component implements IRoute
{
@Exclude() router: Router = new Router (this)
routeName = 'page1'
}
So child routes are identical to parent routes, except that if the child is a terminal/leaf-node, then it has no children, so doesn't need to implement childRoute
.
Use the history API to map changes to the history (e.g. back button etc.) to the root route:
history.listen ((historyLocation, action) => {
this.router.go (location.pathname, action)
})
The go
method of the router sets the parent-relative child route. The childRouteName
property of the router is either ''
, meaning no child is set, or is set to the name of a child route. It should be used to represent the currently selected item in any scenario where that makes sense (e.g. wizards, lists of editable items).
Can include this in the main pickle API at the end of the month.
checked in