:metal: KnockoutJS Goodies Monorepo
Nested routes are registered by
import * as ko from 'knockout'
import { Router } from '@profiscience/knockout-contrib'
Router.useRoutes({
'/user': {
'/': 'user-list',
'/new': 'user-create',
'/:id': 'user-show',
'/:id/edit': 'user-edit',
},
})
import * as ko from 'knockout'
import { Route, Router } from '@profiscience/knockout-contrib'
Router.useRoutes([
new Route('/user', [
new Route('/', 'user-list'),
new Route('/', 'user-create'),
new Route('/:id', 'user-show'),
new Route('/:id/edit', 'user-edit'),
]),
])
You can also mix-and-match, should you find it appropriate…
import * as ko from 'knockout'
import { Route, Router } from '@profiscience/knockout-contrib'
Router.useRoutes([
new Route('/user', {
'/': 'user-list',
'/new': 'user-create',
'/:id': 'user-show',
'/:id/edit': 'user-edit',
}),
])
If an empty template isn’t enough for you, you can still pass a component
name to the route along with your nested routes, and include a <router></router>
in that component.
import ko from 'knockout'
import { Router } from '@profiscience/knockout-contrib'
Router.useRoutes({
'/user': [
'user-header',
{
'/': 'user-list',
'/new': 'user-create',
'/:id': 'user-show',
'/:id/edit': 'user-edit',
},
],
})
ko.components.register('user-header', {
template: `
<a data-bind="path: '/'">
List
</a>
<a data-bind="path: '/new'">
New User
</a>
<router></router>
`,
})
One short-lived feature of the router was passthrough params; for reasons outlined in this blog post, that presented issues with optimal execution of nested router middleware. In order to pass data between parent and child routers, it must be attached to the context in a middleware function. This is an opinionated approach that prevents you from doing initialization/data fetching in the viewModels, but this should be seen as a best practice and not a downfall as it leads to more modularization, easier unit testing of business logic, and easier to maintain viewModels as they are concerned only with UI interactions. See best practices for more.