From ff5a50856fc2a5265f5cb4b4ba33886e7c7304fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 14 Oct 2021 09:49:26 +0000 Subject: [PATCH] [ADD] developer: add javascript framework overview closes odoo/documentation#1181 Signed-off-by: Antoine Vandevenne (anv) --- content/developer/reference/javascript.rst | 1 + .../javascript/framework_overview.rst | 193 ++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 content/developer/reference/javascript/framework_overview.rst diff --git a/content/developer/reference/javascript.rst b/content/developer/reference/javascript.rst index 0c973a34f..da65b8948 100644 --- a/content/developer/reference/javascript.rst +++ b/content/developer/reference/javascript.rst @@ -7,6 +7,7 @@ Javascript Modules .. toctree:: :titlesonly: + javascript/framework_overview javascript/javascript_cheatsheet javascript/javascript_reference javascript/mobile diff --git a/content/developer/reference/javascript/framework_overview.rst b/content/developer/reference/javascript/framework_overview.rst new file mode 100644 index 000000000..b832828ae --- /dev/null +++ b/content/developer/reference/javascript/framework_overview.rst @@ -0,0 +1,193 @@ +================== +Framework Overview +================== + +Introduction +============ + +The Odoo Javascript framework is a set of features/building blocks provided by +the ``web/`` addon to help build odoo applications running in the browser. At +the same time, the Odoo Javascript framework is a single page application, +usually known as the *web client* (available at the url ``/web``). + +The web client started as an application made with a custom class and widget +system, but it is now transitioning to using native javascript classes instead, +and Owl as a component system. This explains why both systems are currently in +use in the codebase. + +From a high-level perspective, the web client is a single-page application: it +does not need to request a full page from the server each time the user performs +an action. Instead, it only requests what it needs and then replaces/updates the +current screen accordingly. Also, it manages the url to keep it in sync with +the current state. + +The javascript framework (all or some parts) is also used in other situations, +such as the Odoo website or the point of sale. This reference is mostly focused +on the web client. + +.. note:: + + It is common in the Odoo ecosystem to see the words *frontend* and *backend* + as synonyms for the odoo website (public) and the web client, respectively. + This terminology is not to be confused with the more common use of + browser-code (frontend) and server (backend). + +.. note:: + + In this documentation, the word *component* always refers to new Owl + components, and *widget* refers to old Odoo widgets. + +.. note:: + + All new development should be done in Owl, if possible! + +Code structure +============== + +The ``web/static/src`` folder contains all the ``web/`` javascript (and css and +templates) codebase. Here is a list of the most important folders: + +- ``core/`` most of the low level features +- ``fields/`` all field components +- ``views/`` all javascript views components (``form``, ``list``, ...) +- ``search/`` control panel, search bar, search panel, ... +- ``webclient/`` the web client specific code: navbar, user menu, action service, ... + +The ``web/static/src`` is the root folder. Everything inside can simply be +imported by using the ``@web`` prefix. For example, here is how one can import +the ``memoize`` function located in ``web/static/src/core/utils/functions``: + +.. code-block:: javascript + + import { memoize } from "@web/core/utils/functions"; + +WebClient Architecture +====================== + +As mentioned above, the web client is an owl application. Here is a slightly +simplified version of its template: + +.. code-block:: xml + + + + + + + + + +As we can see, it basically is a wrapper for a navbar, the current action and +some additional components. The ``ActionContainer`` is a higher order component +that will display the current action controller (so, a client action, or a +specific view in the case of actions of type ``act_window``). Managing actions +is a huge part of its work: the action service keeps in memory a stack of +all active actions (represented in the breadcrumbs), and coordinates each +change. + +Another interesting thing to note is the ``MainComponentsContainer``: it is +simply a component that displays all components registered in the +``main_components`` registry. This is how other parts of the system can extend +the web client. + +Building Blocks +=============== + +Most of the web client is built with a few types of abstractions: registries, +services, components and hooks. + +Registries +---------- + +Registries are basically a simple key/value mapping that stores some specific +kind of objects. They are an important part of the extensibility of the UI: +once some object is registered, the rest of the web client can use it. For +example, the field registry contains all field components (or widgets) that +can be used in views. + +.. code-block:: javascript + + import { registry } from "./core/registry"; + + class MyFieldChar extends owl.Component { + // some code + } + + registry.category("fields").add("my_field_char", MyFieldChar); + +Note that we import the main registry from ``@web/core/registry`` then open the +sub registry ``fields``. + +Services +-------- + +Services are long lived pieces of code that provide a feature. They may be +imported by components (with ``useService``) or by other services. Also, they +can declare a set of dependencies. In that sense, services are basically a DI +(dependency injection) system. For example, the ``notification`` service +provides a way to display a notification, or the ``rpc`` service is the proper +way to perform a request to the Odoo server. + +The following example registers a simple service that displays a notification +every 5 second: + +.. code-block:: javascript + + import { registry } from "./core/registry"; + + const myService = { + dependencies: ["notification"], + start(env, { notification }) { + let counter = 1; + setInterval(() => { + notification.add(`Tick Tock ${counter++}`); + }, 5000); + } + }; + + serviceRegistry.add("myService", myService); + +Components and Hooks +-------------------- + +Components and hooks are ideas coming from the +`Owl component system `_. +Odoo components are simply owl components that are part of the web client. + +`Hooks `_ are a +way to factorize code, even if it depends on lifecycle. This is a +composable/functional way to inject a feature in a component. They can be seen +as a kind of mixin. + +.. code-block:: javascript + + function useCurrentTime() { + const state = useState({ now: new Date() }); + const update = () => state.now = new Date(); + let timer; + onWillStart(() => timer = setInterval(update, 1000)); + onWillUnmount(() => clearInterval(timer)); + return state; + } + +Browser Object +============== + +The javascript framework also provides a special object ``browser`` that +provides access to all browser APIs, like ``location``, ``localStorage`` +or ``setTimeout``. For example, here is how one could use the +``browser.setTimeout`` function: + +.. code-block:: javascript + + import { browser } from "@web/core/browser/browser"; + + // somewhere in code + browser.setTimeout(someFunction, 1000); + +It is mostly interesting for testing purposes: all code using the browser object +can be tested easily by mocking the relevant functions for the duration of the +test. + +.. seealso:: + - `Owl Repository `_ \ No newline at end of file