Home › Learn
Router
Routes with parameters, nested routes, guards, resolvers, lazy loading and hash and history modes.
The router decides which component to show according to the address. It is enabled with provideRouter(routes), and screens are painted wherever you put <router-outlet>. Links are <a routerLink="/path">. (It is not enabled on this page so it does not clobber its anchors.)
Routes, parameters and nesting#
const { component, mount, provideRouter, router } = AngeLite;
class Home {}
component(Home, { template: `<h2>Home</h2>` });
// the parent has its own outlet for the child routes
class Admin {}
component(Admin, { template: `<nav>Administration</nav><router-outlet></router-outlet>` });
class AdminHome {} component(AdminHome, { template: `<h3>Summary</h3>` });
class AdminUser { id = () => router.params().id; }
component(AdminUser, { template: `<h3>User {{ id() }}</h3>` });
class NotFound {} component(NotFound, { template: `<h2>404</h2>` });
provideRouter([
{ path: '/', component: Home },
{ path: 'admin', component: Admin, children: [
{ path: '', component: AdminHome },
{ path: 'users/:id', component: AdminUser }
] },
{ path: 'old', redirectTo: '/' },
{ path: '**', component: NotFound }
]);
class App {}
component(App, {
template: `
<nav><a routerLink="/">Home</a> <a routerLink="/admin/users/42">User 42</a></nav>
<router-outlet></router-outlet>`
});
mount(App, document.getElementById('app'));:iddeclares a parameter;router.params()returns it (already decoded) as a reactive object.childrennests routes: the parent component paints the children in its own<router-outlet>, and is not rebuilt when only the child route changes.''is a parent's index route;**catches everything else;redirectToreplaces the history entry.
Guards#
A route can declare canActivate: [guard]. A guard receives { path, params, query, route } and returns true (proceed), false (stay where you were: the address is restored) or a route (redirect). It can be asynchronous; if the user navigates elsewhere while it waits, the old navigation is cancelled.
const adminOnly = async ({ path }) => (await session.isAdmin()) || '/login';
provideRouter([
{ path: 'admin', component: Admin, canActivate: [adminOnly] },
{ path: 'login', component: Login }
]);Data before painting: resolvers and query#
resolve: { user: ({ params }) => … } loads data before showing the page; if it fails, you stay where you were and the error is logged. router.data().user delivers it. Query parameters (?page=2) arrive in router.query() as { page: '2' }.
{ path: 'users/:id', component: User,
resolve: { user: ({ params }) => http.get('/users/' + params.id) } }
// in the component: router.data().user · router.query().tabLazy-loading screens#
load: () => import('./screen.js') downloads a route's code the first time it is visited (the module exports the component as default, or is the component). If the download fails, the error is logged and you stay on the previous screen.
{ path: 'reports', load: () => import('./reports.js') }Hash and history modes#
By default the router uses the hash (#/path): it works on any static hosting. With provideRouter(routes, { mode: 'history', base: '/app' }) it uses real paths; the server must then return the same page for all of them. Clicks on routerLink navigate without reloading (with Ctrl, Cmd, Shift or target the browser acts as usual), and a shared address such as /app#/path lands on /app/path.
router.navigate('/path?x=1') adds a history entry; router.navigate('/path', { replace: true }) replaces the current one. In history mode a path such as //somewhere-else never takes the user out of the site.