From ddb2d20b307bbbdca999c2db08ce129ae3432294 Mon Sep 17 00:00:00 2001 From: fdardenne Date: Thu, 1 Dec 2022 09:24:33 +0100 Subject: [PATCH] [ADD] developer: add a tutorial on Owl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds the introduction and the chapter 1 of the new Owl/JavaScript framework tutorial. This new tutorial allows people to discover Owl and the building blocks of the Odoo JavaScript framework. Co-authored-by: Géry Debongnie Co-authored-by: Antoine Vandevenne (anv) --- conf.py | 1 + content/developer/howtos.rst | 1 + .../howtos/discover_js_framework.rst | 53 +++ .../discover_js_framework/01_components.rst | 319 ++++++++++++++++++ .../01_components/card.png | Bin 0 -> 5516 bytes .../01_components/counter.png | Bin 0 -> 4412 bytes .../01_components/create_todo.png | Bin 0 -> 5942 bytes .../01_components/delete_todo.png | Bin 0 -> 7161 bytes .../01_components/overview.png | Bin 0 -> 15213 bytes .../01_components/todo.png | Bin 0 -> 5553 bytes .../01_components/todo_list.png | Bin 0 -> 5766 bytes .../01_components/toggle_todo.png | Bin 0 -> 6389 bytes 12 files changed, 374 insertions(+) create mode 100644 content/developer/howtos/discover_js_framework.rst create mode 100644 content/developer/howtos/discover_js_framework/01_components.rst create mode 100644 content/developer/howtos/discover_js_framework/01_components/card.png create mode 100644 content/developer/howtos/discover_js_framework/01_components/counter.png create mode 100644 content/developer/howtos/discover_js_framework/01_components/create_todo.png create mode 100644 content/developer/howtos/discover_js_framework/01_components/delete_todo.png create mode 100644 content/developer/howtos/discover_js_framework/01_components/overview.png create mode 100644 content/developer/howtos/discover_js_framework/01_components/todo.png create mode 100644 content/developer/howtos/discover_js_framework/01_components/todo_list.png create mode 100644 content/developer/howtos/discover_js_framework/01_components/toggle_todo.png diff --git a/conf.py b/conf.py index f5800a5f5..354074564 100644 --- a/conf.py +++ b/conf.py @@ -63,6 +63,7 @@ add_function_parentheses = True source_read_replace_vals = { 'GITHUB_PATH': f'https://github.com/odoo/odoo/blob/{version}', 'GITHUB_ENT_PATH': f'https://github.com/odoo/enterprise/blob/{version}', + 'OWL_PATH': f'https://github.com/odoo/owl/blob/master', } # Add extensions directory to PYTHONPATH diff --git a/content/developer/howtos.rst b/content/developer/howtos.rst index 203807a7f..2e446cff4 100644 --- a/content/developer/howtos.rst +++ b/content/developer/howtos.rst @@ -8,6 +8,7 @@ Tutorials :titlesonly: howtos/rdtraining + howtos/discover_js_framework howtos/website howtos/backend howtos/web_services diff --git a/content/developer/howtos/discover_js_framework.rst b/content/developer/howtos/discover_js_framework.rst new file mode 100644 index 000000000..8a6eb08b3 --- /dev/null +++ b/content/developer/howtos/discover_js_framework.rst @@ -0,0 +1,53 @@ +:show-content: + +================================= +Discover the JavaScript Framework +================================= + +.. toctree:: + :titlesonly: + :glob: + + discover_js_framework/* + +For this training, we will step into the shoes of the IT staff at the fictional company Awesome +T-Shirt, which is dedicated to printing custom t-shirts for online customers. The Awesome T-Shirt +company uses Odoo to manage orders and has created a dedicated Odoo module to manage their workflow. +The project is currently a simple kanban view, with a few columns. + +The usual process is as follows: a customer looking for a nice t-shirt can simply order it from the +Awesome T-Shirt site and give the url for any image they want. They must also fill in some basic +information, such as the desired size and quantity of t-shirts. Once they have confirmed their +order, and once the payment has been validated, the system will create a task in our application. + +The big boss of Awesome T-shirt, Bafien Carpink, is unhappy with our implementation. He believes +that by micromanaging more, he will be able to get more revenue from his employees. As the IT staff +for Awesome T-shirt, we are responsible with improving the system. Various independent tasks must be +performed. + +Let us now practice our Odoo skills! + +.. _howtos/discover_js_framework/setup: + +Setup +===== + +To follow the training, it is necessary to have basic knowledge on Git and a recent version of Odoo +installed. If you have not installed it yet, we recommend installing it from :ref:`source +` (:dfn:`running Odoo from source code`). + +To setup your development environment, you can also follow the dedicated chapter in :doc:`Getting +Started: Development environment setup ` tutorial. + +The last things to do are: + +- Clone the `official Odoo tutorials repository `_ and switch to + the branch `{BRANCH}`. +- Add the cloned repository to the :option:`--addons-path `. +- Start a new Odoo database and install the modules `owl_playground`, `awesome_tshirt`, and + `awesome_gallery`. + +Exercises +========= + +* :doc:`discover_js_framework/01_components` diff --git a/content/developer/howtos/discover_js_framework/01_components.rst b/content/developer/howtos/discover_js_framework/01_components.rst new file mode 100644 index 000000000..4887bdc9c --- /dev/null +++ b/content/developer/howtos/discover_js_framework/01_components.rst @@ -0,0 +1,319 @@ +===================== +Chapter 1: Components +===================== + +This chapter introduces the `Owl framework `_, a tailor-made component +system for Odoo. The main building blocks of OWL are `components +<{OWL_PATH}/doc/reference/component.md>`_ and `templates +<{OWL_PATH}/doc/reference/templates.md>`_. + +In Owl, every part of user interface is managed by a component: they hold the logic and define the +templates that are used to render the user interface. In practice, a component is represented by a +small JavaScript class subclassing the `Component` class. + +.. _jstraining/chapter1/intro_example: + +.. example:: + The `Counter` class implements a component that holds the internal state of a counter and defines + how it should be incremented. + + .. code-block:: js + + const { Component, useState } = owl; + + class Counter extends Component { + static template = "my_module.Counter"; + + state = useState({ value: 0 }); + + increment() { + this.state.value++; + } + } + + The `Counter` class specifies the name of the template to render. The template is written in XML + and defines a part of user interface. + + .. code-block:: xml + + + +

Counter:

+ +
+
+ + You maybe noticed the `owl="1"` temporary attribute, it allows Odoo to differentiate Owl + templates from the old JavaScript framework templates. + +Let us take some time to get used to Owl itself. Below, you will find a series of exercises +intended to quickly understand and practice the basics of Owl. + +.. todo:: update screenshot + +.. admonition:: Goal + + Here is an overview of what we are going to achieve in this chapter. + + .. image:: 01_components/overview.png + :scale: 50% + :align: center + :alt: Overview of chapter 1. + +.. spoiler:: Solutions + + The solutions for each exercise of the chapter are hosted on the `official Odoo tutorials + repository `_. + +1. Displaying a counter +======================= + +As a first exercise, let us implement a counter in the `Playground` component located in +:file:`owl_playground/static/src/`. + +.. exercise:: + + #. Modify :file:`playground.js` so that it acts as a counter like in :ref:`the example above + `. You will need to use the `useState + <{OWL_PATH}/doc/reference/hooks.md#usestate>`_ function so that the component is re-rendered + whenever any part of the state object has been read by this component is modified. + #. In the same component, create an `increment` method. + #. Modify the template in :file:`playground.xml` so that it displays your counter variable. Use + `t-esc <{OWL_PATH}/doc/reference/templates.md#outputting-data>`_ to output the data. + #. Add a button in the template and specify a `t-on-click + <{OWL_PATH}/doc/reference/event_handling.md#event-handling>`_ attribute in the button to + trigger the `increment` method whenever the button is clicked. + + .. image:: 01_components/counter.png + :scale: 70% + :align: center + :alt: A counter component. + +2. Extract counter in a component +================================= + +For now we have the logic of a counter in the `Playground` component, let us see how to create a +sub-component from it. + +.. exercise:: + + #. Extract the counter code from the `Playground` component into a new `Counter` component. + #. You can do it in the same file first, but once it's done, update your code to move the + `Counter` in its own file. + #. Make sure the template is in its own file, with the same name. + +.. important:: + Don't forget :code:`/** @odoo-module **/` in your JavaScript files. More information on this can + be found :ref:`here `. + +3. A todo component +=================== + +We will create new components in :file:`owl_playground/static/src/` to keep track of a list of +todos. This will be done incrementally in multiple exercises that will introduce various concepts. + +.. exercise:: + + #. Create a `Todo` component that receive a `todo` object in `props + <{OWL_PATH}/doc/reference/props.md>`_, and display it. It should show something like + **3. buy milk**. + #. Add the Bootstrap classes `text-muted` and `text-decoration-line-through` on the task if it is + done. To do that, you can use `dynamic attributes + <{OWL_PATH}/doc/reference/templates.md#dynamic-attributes>`_ + #. Modify :file:`owl_playground/static/src/playground.js` and + :file:`owl_playground/static/src/playground.xml` to display your new `Todo` component with + some hard-coded props to test it first. + + .. example:: + + .. code-block:: javascript + + setup() { + ... + this.todo = { id: 3, description: "buy milk", done: false }; + } + + .. image:: 01_components/todo.png + :scale: 70% + :align: center + :alt: A Todo component + +.. seealso:: + `Owl: Dynamic class attributes <{OWL_PATH}/doc/reference/templates.md#dynamic-class-attribute>`_ + +4. Props validation +=================== + +The `Todo` component has an implicit API. It expects to receive in its props the description of a +todo object in a specified format: `id`, `description` and `done`. Let us make that API more +explicit. We can add a props definition that will let Owl perform a validation step in :ref:`dev +mode `. It is a good practice to do that for every component. + +.. exercise:: + + #. Add `props validation <{OWL_PATH}/doc/reference/props.md#props-validation>`_ to the `Todo` + component. + #. Make sure it passes in :ref:`dev mode `. + #. Remove `done` from the props and reload the page. The validation should fail. + +5. A list of todos +================== + +Now, let us display a list of todos instead of just one todo. For now, we can still hard-code the +list. + +.. exercise:: + + #. Change the code to display a list of todos instead of just one, and use `t-foreach + <{OWL_PATH}/doc/reference/templates.md#loops>`_ in the template + #. Think about how it should be keyed with the `t-key` directive. + + .. image:: 01_components/todo_list.png + :scale: 70% + :align: center + :alt: A TodoList + +6. Adding a todo +================ + +So far, the todos in our list are hard-coded. Let us make it more useful by allowing the user to add +a todo to the list. + +.. exercise:: + + #. Add an input above the task list with placeholder *Enter a new task*. + #. Add an `event handler <{OWL_PATH}/doc/reference/event_handling.md>`_ on the `keyup` event + named ``addTodo``. + #. Implement `addTodo` to check if enter was pressed (:code:`ev.keyCode === 13`), and in that + case, create a new todo with the current content of the input as the description. + #. Make sure it has a unique id. It can be just a counter that increments at each todo. + #. Then, clear the input of all content. + #. Bonus point: don't do anything if the input is empty. + + .. note:: + Notice that nothing updates in the UI: this is because Owl does not know that it should update + the UI. This can be fixed by wrapping the todo list in a `useState` hook. + + .. code-block:: javascript + + this.todos = useState([]); + + .. image:: 01_components/create_todo.png + :scale: 70% + :align: center + :alt: Creating todos + +.. seealso:: + `Owl: Reactivity <{OWL_PATH}/doc/reference/reactivity.md>`_ + +7. Focusing the input +===================== + +Let's see how we can access the DOM with `t-ref <{OWL_PATH}/doc/reference/refs.md>`_ and `useRef +<{OWL_PATH}/doc/reference/hooks.md#useref>`_. + +.. exercise:: + + #. Focus the `input` from the previous exercise when the dashboard is `mounted + <{OWL_PATH}/doc/reference/component.md#mounted>`_. + #. Bonus point: extract the code into a specialized `hook <{OWL_PATH}/doc/reference/hooks.md>`_ + `useAutofocus`. + +.. seealso:: + `Owl: Component lifecycle <{OWL_PATH}/doc/reference/component.md#lifecycle>`_ + +8. Toggling todos +================= + +Now, let's add a new feature: mark a todo as completed. This is actually trickier than one might +think. The owner of the state is not the same as the component that displays it. So, the `Todo` +component needs to communicate to its parent that the todo state needs to be toggled. One classic +way to do this is by using a `callback prop +<{OWL_PATH}/doc/reference/props.md#binding-function-props>`_ `toggleState`. + +.. exercise:: + + #. Add an input with the attribute :code:`type="checkbox"` before the id of the task, which must + be checked if the state `done` is true. + #. Add a callback props `toggleState`. + #. Add a `click` event handler on the input in the `Todo` component and make sure it calls the + `toggleState` function with the todo id. + #. Make it work! + + .. image:: 01_components/toggle_todo.png + :scale: 70% + :align: center + :alt: Toggling todos + +9. Deleting todos +================= + +The final touch is to let the user delete a todo. + +.. exercise:: + + #. Add a new callback prop `removeTodo`. + #. Insert :code:`` in the template of the `Todo` component. + #. Whenever the user clicks on it, it should call the `removeTodo` method. + + .. image:: 01_components/delete_todo.png + :scale: 70% + :align: center + :alt: Deleting todos + +10. Generic components with slots +================================= + +Owl has a powerful `slot <{OWL_PATH}/doc/reference/slots.md>`_ system to allow you to write generic +components. This is useful to factorize the common layout between different parts of the interface. + +.. exercise:: + + #. Write a `Card` component using the following Bootstrap HTML structure: + + .. code-block:: html + +
+ ... +
+
Card title
+

+ Some quick example text to build on the card title and make up the bulk + of the card's content. +

+ Go somewhere +
+
+ + #. This component should have two slots: one slot for the title, and one for the content (the + default slot). + + .. example:: + Here is how one could use it: + + .. code-block:: html + + + Card title +

Some quick example text...

+ Go somewhere +
+ + #. Bonus point: if the `title` slot is not given, the `h5` should not be rendered at all. + + .. image:: 01_components/card.png + :scale: 70% + :align: center + :alt: Creating card with slots + +.. seealso:: + `Bootstrap: documentation on cards `_ + +11. Go further +============== + +.. exercise:: + + #. Add prop validation on the `Card` component. + #. Try to express in the props validation system that it requires a `default` slot, and an + optional `title` slot. diff --git a/content/developer/howtos/discover_js_framework/01_components/card.png b/content/developer/howtos/discover_js_framework/01_components/card.png new file mode 100644 index 0000000000000000000000000000000000000000..7cb843199942f95c33485dcc1a274d3ea0cd0163 GIT binary patch literal 5516 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 literal 0 HcmV?d00001 diff --git a/content/developer/howtos/discover_js_framework/01_components/counter.png b/content/developer/howtos/discover_js_framework/01_components/counter.png new file mode 100644 index 0000000000000000000000000000000000000000..cd8eb5f12282484387f37d0091c85f6e4f280deb GIT binary patch literal 4412 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 literal 0 HcmV?d00001 diff --git a/content/developer/howtos/discover_js_framework/01_components/create_todo.png b/content/developer/howtos/discover_js_framework/01_components/create_todo.png new file mode 100644 index 0000000000000000000000000000000000000000..e5d8eadae466169c1fb2cfe80cf17159c28024f5 GIT binary patch literal 5942 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%0DEkw4$cE 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 literal 0 HcmV?d00001 diff --git a/content/developer/howtos/discover_js_framework/01_components/overview.png b/content/developer/howtos/discover_js_framework/01_components/overview.png new file mode 100644 index 0000000000000000000000000000000000000000..d183bffa38d516d3530c777e385103e51fe0dce9 GIT binary patch literal 15213 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 literal 0 HcmV?d00001 diff --git a/content/developer/howtos/discover_js_framework/01_components/todo.png b/content/developer/howtos/discover_js_framework/01_components/todo.png new file mode 100644 index 0000000000000000000000000000000000000000..e1733c8e783741320fd35afb2786ba56dce88ddf GIT binary patch literal 5553 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 YD9aO8r}5M8e}1NFsOml_Q??HMFRRD4$p8QV literal 0 HcmV?d00001 diff --git a/content/developer/howtos/discover_js_framework/01_components/todo_list.png b/content/developer/howtos/discover_js_framework/01_components/todo_list.png new file mode 100644 index 0000000000000000000000000000000000000000..7de8451578cc14ff5ae21a54910867b145bc866d GIT binary patch literal 5766 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 literal 0 HcmV?d00001 diff --git a/content/developer/howtos/discover_js_framework/01_components/toggle_todo.png b/content/developer/howtos/discover_js_framework/01_components/toggle_todo.png new file mode 100644 index 0000000000000000000000000000000000000000..913bfdac9cb93e6c8cfba6cbd738bef0ea43c7cc GIT binary patch literal 6389 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 RPyP8I0Rd^N;*_5U{})_OXlMWc literal 0 HcmV?d00001