From c172b31481d719f90764fd105d58a297efc68d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Mon, 26 Aug 2019 15:33:38 +0200 Subject: [PATCH] [DOC] router: add documentation --- doc/readme.md | 11 +++- doc/router.md | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 doc/router.md diff --git a/doc/readme.md b/doc/readme.md index 9bfa11a9..5440caee 100644 --- a/doc/readme.md +++ b/doc/readme.md @@ -12,15 +12,18 @@ owl core EventBus Observer + router + Link + Router store Store ConnectedComponent utils - whenReady + debounce + escape loadJS loadTemplates - escape - debounce + whenReady ``` ## Reference @@ -30,6 +33,7 @@ owl - [Event Bus](event_bus.md) - [Observer](observer.md) - [QWeb](qweb.md) +- [Router](router.md) - [Store](store.md) - [Utils](utils.md) - [Virtual DOM](vdom.md) @@ -42,3 +46,4 @@ owl - [Comparison with React/Vue](comparison.md) - [Tooling](tooling.md) +- [Templates to start Owl applications (external link)](https://github.com/ged-odoo/owl-templates) \ No newline at end of file diff --git a/doc/router.md b/doc/router.md new file mode 100644 index 00000000..142eb53b --- /dev/null +++ b/doc/router.md @@ -0,0 +1,172 @@ +# 🦉 Router 🦉 + +## Content + +- [Overview](#overview) +- [Example](#example) +- [Reference](#reference) + - [Route Definition](#route-definition) + - [Router](#router) + - [Navigation Guards](#navigation-guards) + - [`t-routecomponent`](#t-routecomponent) + - [Link](#link) + +## 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: + +- `history` or `hash` mode +- declarative routes +- route redirection +- navigation guards +- parameterized routes +- a `` component +- a `t-routecomponent` directive + +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: + +- declare some routes +- create a router +- add it to the environment + +```js +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; +} +``` + +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: + +- `name` (optional): a (unique) string useful to identify the current route. If not + given, it will be assigned an automatic name, +- `path`: a string describing the url. It can be static: `/admin` or dynamic: `/users/{{id}}`. + It also can be `*`, to catch all remaining routes. +- `component` (optional): an Owl component that will be used by the `t-routecomponent` + directive if the route is active +- `redirect` (optional): should be destination object (with optional keys `path`, `to` and `params`) if given, the application will be redirected to the destination whenever we match this route +- `beforeRouteEnter`: defines a [navigation guard](#navigation-guards). + +### `Router` + +The `Router` constructor takes three arguments: + +- `env`: a valid environment, +- a list of routes, +- an optional object (with the only key `mode` which can be `history` (default + value) or `hash`). + +```js +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). + +```js +await router.start(); +``` + +Once started, the router will keep track of the current url and reflect its +value in two keys: + +- `router.currentRoute` +- `router.currentParams` + +The router also has a `navigate` method, useful to programmatically change the +application to another state (and the url): + +```js +router.navigate({to: 'USER', params: {id: 51}}); +``` + +### Navigation Guards + +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. + +```js +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. + +### `t-routecomponent` + +The `t-routecomponent` directive directs Owl to render the component associated +to the currently active route (if any): + +```xml +
+ + +
+``` + + +### `Link` + +The `Link` component is a Owl component which render as 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. + +```xml +Home +```