🦉 Router 🦉

Content

Overview

It is often useful to organize an application around urls. If the application is a single page application, then we need a way to manage those urls in the browser. This is why there are many different routers for different frameworks. A generic router can do the job just fine, but a specialized router for Owl can give a better developer experience.

The Owl router support the following features:

Note that it is still in early stage of developments, and there are probably still some issues.

Example

To use the Owl router, there are some steps that needs to be done:

async function protectRoute({ env, to }) { if (!env.session.authUser) { env.session.setNextRoute(to.name); return { to: "SIGN_IN" }; } return true; } export const ROUTES = [ { name: "LANDING", path: "/", component: Landing }, { name: "TASK", path: "/tasks/{{id}}", component: Task }, { name: "SIGN_UP", path: "/signup", component: SignUp }, { name: "SIGN_IN", path: "/signin", component: SignIn }, { name: "ADMIN", path: "/admin", component: Admin, beforeRouteEnter: protectRoute }, { name: "ACCOUNT", path: "/account", component: Account, beforeRouteEnter: protectRoute }, { name: "UNKNOWN", path: "*", redirect: { to: "LANDING" } } ]; function makeEnvironment() { ... const env = { qweb }; env.session = new Session(env); env.router = new owl.router.Router(env, ROUTES); await env.router.start(); return env; } App.env = makeEnvironment(); // create root component here

Notice that the router needs to be started. This is an asynchronous operation because it needs to apply the potential navigation guards on the current route (which may or may not mean that the application is redirected to another route).

Reference

Route definition

A route need to be defined as an object with the following keys:

Router

The Router constructor takes three arguments:

history will use the browser History API as the mechanism to manage URL.
Example: https://yourdomain.tld/my_custom_route.
For this mechanism to work, you need a way to configure your web server accordingly.

hash will manipulate the hash of the URL.
Example: https://yourdomain.tld/index.html#/my_custom_route.

const ROUTES = [...]; const router = new owl.router.Router(env, ROUTES, {mode: 'history'});

Note that the route are defined in a list, and the order matters: the router tries to find a match by going down the list.

The router needs to be added to the environment in the router sub key.

Once a router is created, it needs to be started. This is necessary to initialize its current state to the current URL (and also, to potentially apply any navigation guards and/or redirecting).

await router.start();

Once started, the router will keep track of the current url and reflect its value in two keys:

The router also has a navigate method, useful to programmatically change the application to another state (and the url):

router.navigate({ to: "USER", params: { id: 51 } });

Navigation guards are very useful to be able to execute some business logic/ perform some actions or redirect to other routes whenever the application is entering a new route. For example, the following guard checks if there is an authenticated user, and if it is not the case, redirect to the sign in route.

async function protectRoute({ env, to }) { if (!env.session.authUser) { env.session.setNextRoute(to.name); return { to: "SIGN_IN" }; } return true; }

A navigation guard is a function that returns a promise, which either resolves to true (the navigation is accepted), or to another destination object.

RouteComponent

The RouteComponent component directs Owl to render the component associated to the currently active route (if any):

<div t-name="App"> <NavBar /> <RouteComponent /> </div>

The Link component is a Owl component which render as a <a> tag with any content. It will compute the proper href from its props, and allow Owl to properly navigate to a given url if clicked on it.

<Link to="'HOME'">Home</Link>