[DOC] improve hooks and qweb doc

Closes #358
Closes #359
This commit is contained in:
Aaron Bohy
2019-10-18 09:22:28 +02:00
committed by Géry Debongnie
parent 0aeebd7b6e
commit 1bb4577ec1
2 changed files with 27 additions and 26 deletions
+16 -16
View File
@@ -35,7 +35,7 @@ Owl hooks serve the same purpose, except that they work for class components
there seems to be the misconception that hooks are in opposition to class. This there seems to be the misconception that hooks are in opposition to class. This
is clearly not true, as shown by Owl hooks). is clearly not true, as shown by Owl hooks).
Hooks works beautifully with Owl components: they solve the problems mentioned Hooks work beautifully with Owl components: they solve the problems mentioned
above, and in particular, they are the perfect way to make your component above, and in particular, they are the perfect way to make your component
reactive. reactive.
@@ -127,7 +127,7 @@ class SomeComponent extends Component {
### One rule ### One rule
There is only one rule: every hook for a component have to be called in the There is only one rule: every hook for a component has to be called in the
constructor (or in class fields): constructor (or in class fields):
```js ```js
@@ -152,14 +152,14 @@ class SomeComponent extends Component {
} }
``` ```
Hooks can get a reference to the currently being defined component with the In a hook, the `Component.current` static property is the reference to the
`Component.current` static property. This is why they need to be called in the component instance that is currently being created. Hooks need to be called in
constructor. the constructor to ensure that this reference is properly set.
### `useState` ### `useState`
The `useState` hook is certainly the most important hooks for Owl components: The `useState` hook is certainly the most important hook for Owl components:
this is what enables component to be reactive, to react to state change. this is what allows a component to be reactive, to react to state change.
The `useState` hook has to be given an object or an array, and will return The `useState` hook has to be given an object or an array, and will return
an observed version of it (using a `Proxy`). an observed version of it (using a `Proxy`).
@@ -183,25 +183,25 @@ class Counter extends owl.Component {
### `onMounted` ### `onMounted`
`onMounted` is not an user hook, but is a building block designed to help make useful `onMounted` is not a user hook, but is a building block designed to help make useful
abstractions. `onMounted` registers a callback, which will be called when the component abstractions. `onMounted` registers a callback, which will be called when the component
is mounted (see example on top of this page). is mounted (see example on top of this page).
### `onWillUnmount` ### `onWillUnmount`
`onWillUnmount` is not an user hook, but is a building block designed to help make useful `onWillUnmount` is not a user hook, but is a building block designed to help make useful
abstractions. `onWillUnmount` registers a callback, which will be called when the component abstractions. `onWillUnmount` registers a callback, which will be called when the component
is unmounted (see example on top of this page). is unmounted (see example on top of this page).
### `onWillPatch` ### `onWillPatch`
`onWillPatch` is not an user hook, but is a building block designed to help make useful `onWillPatch` is not a user hook, but is a building block designed to help make useful
abstractions. `onWillPatch` registers a callback, which will be called just abstractions. `onWillPatch` registers a callback, which will be called just
before the component patched. before the component patched.
### `onPatched` ### `onPatched`
`onPatched` is not an user hook, but is a building block designed to help make useful `onPatched` is not a user hook, but is a building block designed to help make useful
abstractions. `onPatched` registers a callback, which will be called just abstractions. `onPatched` registers a callback, which will be called just
after the component patched. after the component patched.
@@ -305,7 +305,7 @@ The `t-ref` directive also accepts dynamic values with string interpolation
<div t-ref="component_{{someCondition ? '1' : '2'}}"/> <div t-ref="component_{{someCondition ? '1' : '2'}}"/>
``` ```
Here, the references needs to be set like this: Here, the references need to be set like this:
```js ```js
this.ref1 = useRef("component_1"); this.ref1 = useRef("component_1");
@@ -321,8 +321,8 @@ The environment is sometimes useful to share some common information between
all components. But sometimes, we want to _scope_ that knowledge to a subtree. all components. But sometimes, we want to _scope_ that knowledge to a subtree.
For example, if we have a form view component, maybe we would like to make some For example, if we have a form view component, maybe we would like to make some
`model` object available to all sub component, but not to the whole application. `model` object available to all sub components, but not to the whole application.
This is where the `useSubEnv` hook may be useful: it let a component add some This is where the `useSubEnv` hook may be useful: it lets a component add some
information to the environment in a way that only the component and its children information to the environment in a way that only the component and its children
can access it: can access it:
@@ -366,7 +366,7 @@ But, like every good things in life, hooks should be used with moderation. They
not the solution to every problem. not the solution to every problem.
- they may be overkill: if your component needs to perform some action specific - they may be overkill: if your component needs to perform some action specific
to him (so, the specific code does not need to be shared), there is nothing to itself (so, the specific code does not need to be shared), there is nothing
wrong with a simple class method: wrong with a simple class method:
```js ```js
@@ -389,7 +389,7 @@ not the solution to every problem.
Note that the second solution is easier to extend in sub components. Note that the second solution is easier to extend in sub components.
- they may be harder to test: if a customized hook inject some external side - they may be harder to test: if a customized hook injects some external side
effect dependency, then it is harder to test without doing some non obvious effect dependency, then it is harder to test without doing some non obvious
manipulation. For example, assume that we want to give a reference to a manipulation. For example, assume that we want to give a reference to a
router in a `useRouter` hook. We could do this: router in a `useRouter` hook. We could do this:
+11 -10
View File
@@ -20,7 +20,7 @@
## Overview ## Overview
[QWeb](https://www.odoo.com/documentation/12.0/reference/qweb.html) is the primary templating engine used by Odoo. It is based on the XML format, and used [QWeb](https://www.odoo.com/documentation/13.0/reference/qweb.html) is the primary templating engine used by Odoo. It is based on the XML format, and used
mostly to generate HTML. In OWL, QWeb templates are compiled into functions that mostly to generate HTML. In OWL, QWeb templates are compiled into functions that
generate a virtual dom representation of the HTML. generate a virtual dom representation of the HTML.
@@ -33,7 +33,7 @@ To avoid element rendering, a placeholder element `<t>` is also available, which
<span t-if="somecondition">Some string</span> <span t-if="somecondition">Some string</span>
<ul t-else="1"> <ul t-else="1">
<li t-foreach="messages" t-as="message"> <li t-foreach="messages" t-as="message">
<t t-esc="message"> <t t-esc="message"/>
</li> </li>
</ul> </ul>
</div> </div>
@@ -85,7 +85,7 @@ instantiated:
const qweb = new owl.QWeb(); const qweb = new owl.QWeb();
``` ```
It's API is quite simple: Its API is quite simple:
- **`constructor(data)`**: constructor. Takes an optional string to add initial - **`constructor(data)`**: constructor. Takes an optional string to add initial
templates (see `addTemplates` for more information on format of the string). templates (see `addTemplates` for more information on format of the string).
@@ -100,7 +100,8 @@ It's API is quite simple:
qweb.addTemplate("mytemplate", "<div>hello</div>"); qweb.addTemplate("mytemplate", "<div>hello</div>");
``` ```
If the optional `allowDuplicate` is set to `true`, then `QWeb` will simply return whenever a template is added for a second time. Otherwise, `QWeb` will crash. If the optional `allowDuplicate` is set to `true`, then `QWeb` will simply
ignore templates added for a second time. Otherwise, `QWeb` will crash.
- **`addTemplates(xmlStr)`**: add a list of templates (identified by `t-name` - **`addTemplates(xmlStr)`**: add a list of templates (identified by `t-name`
attribute). attribute).
@@ -128,13 +129,13 @@ It's API is quite simple:
const str = qweb.renderToString("someTemplate", somecontext); const str = qweb.renderToString("someTemplate", somecontext);
``` ```
- **`registerTemplate(name, template)`**: static function to register an global - **`registerTemplate(name, template)`**: static function to register a global
QWeb template. This is useful for commonly used components accross the QWeb template. This is useful for commonly used components accross the
application, and for making a template available to an application without application, and for making a template available to an application without
having a reference to the actual QWeb instance. having a reference to the actual QWeb instance.
```js ```js
QWeb.registerTemplate("mytemplate", `<div>some template`); QWeb.registerTemplate("mytemplate", `<div>some template</div>`);
``` ```
- **`registerComponent(name, Component)`**: static function to register an OWL Component - **`registerComponent(name, Component)`**: static function to register an OWL Component
@@ -154,7 +155,7 @@ It's API is quite simple:
In some way, a `QWeb` instance is the core of an Owl application. It is the only In some way, a `QWeb` instance is the core of an Owl application. It is the only
mandatory element of an [environment](component.md#environment). As such, it mandatory element of an [environment](component.md#environment). As such, it
has an extra responsability: it can act as an event bus for internal communication has an extra responsibility: it can act as an event bus for internal communication
between Owl classes. This is the reason why `QWeb` actually extends [EventBus](event_bus.md). between Owl classes. This is the reason why `QWeb` actually extends [EventBus](event_bus.md).
## Reference ## Reference
@@ -165,7 +166,7 @@ specific extensions are documented in various other parts of the documentation.
### White Spaces ### White Spaces
White spaces in a templates are handled in a special way: White spaces in a template are handled in a special way:
- consecutive whitespaces are always condensed to a single whitespace - consecutive whitespaces are always condensed to a single whitespace
- if a whitespace-only text node contains a linebreak, it is ignored - if a whitespace-only text node contains a linebreak, it is ignored
@@ -207,7 +208,7 @@ component). For example, `a + b.c(d)` will be converted into:
context["a"] + context["b"].c(context["d"]); context["a"] + context["b"].c(context["d"]);
``` ```
It is useful to explain the various rules that applies on these expressions: It is useful to explain the various rules that apply on these expressions:
1. it should be a simple expression which returns a value. It cannot be a statement. 1. it should be a simple expression which returns a value. It cannot be a statement.
@@ -531,4 +532,4 @@ will stop execution if the browser dev tools are open.
<t t-log="foo"/> <t t-log="foo"/>
``` ```
will print 42 to the console will print 42 to the console.