mithril-nested-router v0.0.5
mithril-nested-router
mithril router with nested routing, reverse and redirect functionality.
Install
npm install mithril-nested-router
How to use
Create router
You can create router using Router.create.
Only first Router.create call makes a singleton router instance.
Once you have created router instance, you can retrieve it later using Router.getInstance().
const m = require('mithril');
const Router = require('mithril-nested-router');
const router1 = Router.create(m);
const router2 = Router.create(m);
const router3 = Router.getInstance();
// router1, router2 and router3 are reference to a same router instance.Define routes
You can define nested routes using Router.prototype.defineRoutes.
Child components are injected into vnode.children of Parent component.
// Parent component
const Page = {
view(vnode) {
return m('div', [
m('p', 'router example'),
m('ul', ['c1', 'c2'].map(name =>
m('li', m('a', {href: `/${name}`, oncreate: router.route.link}, name))
)),
vnode.children
]);
}
};
// Child components
const C1 = {
view(vnode) { return m('p', 'content1'); }
};
const C2 = {
view(vnode) { return m('p', 'content2'); }
};
// Define routes
router.defineRoutes(document.getElementById('root'), '/c1', [
{path: '/', name: 'root', component: Page, routes: [
{path: 'c1', name: 'c1', component: C1},
{path: 'c2', name: 'c2', component: C2},
]}
]);You can pass attrs to a Component using attrs property.
router.defineRoutes(document.getElementById('root'), '/', [
{path: '/', name: 'root', component: Component, attrs: {a: 1, b: 2}}
]);
const Component = {
oninit(vnode) {
console.log(vnode.attrs); // {a: 1, b: 2}
},
...
};You can also use context property with routes property. Context propagates to sub routes.
The example below, C1, C2 and G1 share the same context defined within GrantParent. Context is injected into vnode.attrs.
An attrs or contexts defined within descendants override the same property of context defined within ancestors.
router.defineRoutes(document.getElementById('root'), '/c1', [
{path: '/', name: 'root', component: GrandParent, context: {a: 1}, routes: [
{path: 'c1', name: 'c1', component: C1},
{path: 'c2/', name: 'c2', component: C2, routes: [
{path: 'g1', name: 'g1', component: G1}
]}
]}
]);You can use onmatch instead of component on top level route definition. About onmatch, please refer to mithril document about RouteResolver.
router.defineRoutes(document.getElementById('root'), '/', [
{path: '/',
name: 'root',
onmatch() {
// do some stuff
return Component;
}
}
]);If you define a parameterized route, going from the parameterized route to the same route with a different parameter (e.g. going from /page/1 to /page/2 given a route /page/:id) doesn't invoke component recreation. In other words, oninit and oncreate of the component don't get called. If you want to recreate a component, you can use key. If you set a function as key value, an invocation of the function is done after a route was resolved.
router.defineRoutes(document.getElementById('root'), '/page/1', [
{path: '/page/:id', name: 'page', component: Page, attrs: {key: () => router.route.param('id')}},
]);Get path for name
You can use Router.prototype.reverse to get path for name.
router.defineRoutes(document.getElementById('root'), '/c1', [
{path: '/', name: 'root', component: GrandParent, routes: [
{path: 'c1', name: 'c1', component: C1},
{path: 'c2/', name: 'c2', component: C2, routes: [
{path: 'g1', name: 'g1', component: G1}
]}
]}
]);
console.log(router.reverse('root:c2:g1')); // /c2/g1You can pass routing parameters to Router.prototype.reverse if you defined routes using routing parameters.
router.defineRoutes(document.getElementById('root'), '/x', [
{path: '/', name: 'root', component: Layout, routes: [
{path: ':content', name: 'content', component: Content},
]}
]);
console.log(router.reverse('root:content', {content: 'c1'})); // /c1
console.log(router.reverse('root:content', {content: 'c2'})); // /c2Redirect
You can use Router.prototype.redirect to change route.
router.defineRoutes(document.getElementById('root'), '/c2/1', [
{path: '/', name: 'root', component: Layout, routes: [
{path: 'c1', name: 'c1', component: C1},
{path: 'c2/', name: 'c2', component: C2, routes: [
{path: ':d', name: 'd', component: D}
]}
]}
]);
// Change current route to /c1
router.redirect('root:c1');
// Of course, you can pass routing parameters to redirect method.
router.redirect('root:c2:d', {d: 3});Technically, Router.prototype.redirect gets path for name, and just delegate to m.route.set.
So, Router.prototype.redirect has same functionality as m.route.set. Please refer to mithril documentation about m.route.set
Get m.route
Router.prototype.route getter return m.route. So you can use Router.prototype.route instead of m.route;
License
MIT