mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[REF] component: use 'component' instead of 'widget'
This commit is contained in:
@@ -32,7 +32,7 @@ find some more information [here](doc/comparison.md).
|
|||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
Here is a short example to illustrate interactive widgets:
|
Here is a short example to illustrate interactive components:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<templates>
|
<templates>
|
||||||
|
|||||||
+1
-1
@@ -87,7 +87,7 @@ For example, a simple fade in/out effect can be done with this:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `t-transition` directive can be combined with `t-widget`.
|
The `t-transition` directive can be applied on a node element or on a component.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -91,17 +91,17 @@ there is a syntax highlighter for jsx here on github!
|
|||||||
This is actually a big difference between OWL and React/Vue: components in OWL
|
This is actually a big difference between OWL and React/Vue: components in OWL
|
||||||
are totally asynchronous. They have two asynchronous hooks in their lifecycle:
|
are totally asynchronous. They have two asynchronous hooks in their lifecycle:
|
||||||
|
|
||||||
- `willStart` (before the widget starts rendering)
|
- `willStart` (before the component starts rendering)
|
||||||
- `willUpdateProps` (before new props are set)
|
- `willUpdateProps` (before new props are set)
|
||||||
|
|
||||||
Both these methods can be implemented and return a promise. The rendering will
|
Both these methods can be implemented and return a promise. The rendering will
|
||||||
then wait for these promises to be completed before patching the DOM. This is
|
then wait for these promises to be completed before patching the DOM. This is
|
||||||
useful for some use cases: for example, a widget may want to fetch an external
|
useful for some use cases: for example, a component may want to fetch an external
|
||||||
library (a calendar widget may need a specialized calendar rendering library),
|
library (a calendar component may need a specialized calendar rendering library),
|
||||||
in its willStart hook.
|
in its willStart hook.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
class MyCalendarWidget extends owl.Component {
|
class MyCalendarComponent extends owl.Component {
|
||||||
...
|
...
|
||||||
|
|
||||||
willStart() {
|
willStart() {
|
||||||
|
|||||||
+87
-87
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
- [Overview](#overview)
|
- [Overview](#overview)
|
||||||
- [Example](#example)
|
- [Example](#example)
|
||||||
- [Root Widget And Environment](#root-widget-and-environment)
|
- [Root Component And Environment](#root-component-and-environment)
|
||||||
- [Reference](#reference)
|
- [Reference](#reference)
|
||||||
- [Properties](#properties)
|
- [Properties](#properties)
|
||||||
- [Static Properties](#static-properties)
|
- [Static Properties](#static-properties)
|
||||||
@@ -28,11 +28,11 @@ OWL components are the building blocks for user interface. They are designed to
|
|||||||
1. **declarative:** the user interface should be described in term of the state
|
1. **declarative:** the user interface should be described in term of the state
|
||||||
of the application, not as a sequence of imperative steps.
|
of the application, not as a sequence of imperative steps.
|
||||||
|
|
||||||
2. **composable:** each widget can seamlessly be created in a parent widget by
|
2. **composable:** each component can seamlessly be created in a parent component by
|
||||||
a simple directive in its template.
|
a simple tag or directive in its template.
|
||||||
|
|
||||||
3. **asynchronous rendering:** the framework will transparently wait for each
|
3. **asynchronous rendering:** the framework will transparently wait for each
|
||||||
subwidgets to be ready before applying the rendering. It uses native promises
|
sub components to be ready before applying the rendering. It uses native promises
|
||||||
under the hood.
|
under the hood.
|
||||||
|
|
||||||
4. **uses QWeb as a template system:** the templates are described in XML
|
4. **uses QWeb as a template system:** the templates are described in XML
|
||||||
@@ -41,7 +41,7 @@ OWL components are the building blocks for user interface. They are designed to
|
|||||||
OWL components are defined as a subclass of Component. The rendering is
|
OWL components are defined as a subclass of Component. The rendering is
|
||||||
exclusively done by a [QWeb](qweb.md) template (which needs to be preloaded in QWeb).
|
exclusively done by a [QWeb](qweb.md) template (which needs to be preloaded in QWeb).
|
||||||
Rendering a component generates a virtual dom representation
|
Rendering a component generates a virtual dom representation
|
||||||
of the widget, which is then patched to the DOM, in order to apply the changes in an efficient way.
|
of the component, which is then patched to the DOM, in order to apply the changes in an efficient way.
|
||||||
|
|
||||||
OWL components observe their states, and rerender themselves whenever it is
|
OWL components observe their states, and rerender themselves whenever it is
|
||||||
changed. This is done by an [observer](observer.md).
|
changed. This is done by an [observer](observer.md).
|
||||||
@@ -76,10 +76,10 @@ a state object is defined. It is not mandatory to use the state object, but it
|
|||||||
is certainly encouraged. The state object is [observed](observer.md), and any
|
is certainly encouraged. The state object is [observed](observer.md), and any
|
||||||
change to it will cause a rerendering.
|
change to it will cause a rerendering.
|
||||||
|
|
||||||
## Root Widget And Environment
|
## Root Component And Environment
|
||||||
|
|
||||||
Most of the time, Owl widget will be created automatically by the `t-widget`
|
Most of the time, an Owl component will be created automatically by a tag (or the `t-component`
|
||||||
directive in a template. There is however an obvious exception: the root widget
|
directive) in a template. There is however an obvious exception: the root component
|
||||||
of an Owl application has to be created manually:
|
of an Owl application has to be created manually:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -91,7 +91,7 @@ const app = new App(env);
|
|||||||
app.mount(document.body);
|
app.mount(document.body);
|
||||||
```
|
```
|
||||||
|
|
||||||
The root widget needs an environment. In Owl, an environment is an object with
|
The root component needs an environment. In Owl, an environment is an object with
|
||||||
a `qweb` key, which has to be a [QWeb](qweb.md) instance. This qweb instance will
|
a `qweb` key, which has to be a [QWeb](qweb.md) instance. This qweb instance will
|
||||||
be used to render everything.
|
be used to render everything.
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ easy to test a component.
|
|||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
An Owl component is a small class which represent a widget or some UI element.
|
An Owl component is a small class which represent a component or some UI element.
|
||||||
It exists in the context of an environment (`env`), which is propagated from a
|
It exists in the context of an environment (`env`), which is propagated from a
|
||||||
parent to its children. The environment needs to have a QWeb instance, which
|
parent to its children. The environment needs to have a QWeb instance, which
|
||||||
will be used to render the component template.
|
will be used to render the component template.
|
||||||
@@ -123,7 +123,7 @@ find a template with the component name (or one of its ancestor).
|
|||||||
|
|
||||||
- **`state`** (Object): this is the location of the component's state, if there is
|
- **`state`** (Object): this is the location of the component's state, if there is
|
||||||
any. After the willStart method, the `state` property is observed, and each
|
any. After the willStart method, the `state` property is observed, and each
|
||||||
change will cause the widget to rerender itself.
|
change will cause the component to rerender itself.
|
||||||
|
|
||||||
- **`props`** (Object): this is an object given (in the constructor) by the parent
|
- **`props`** (Object): this is an object given (in the constructor) by the parent
|
||||||
to configure the component. It can be dynamically changed later by the parent,
|
to configure the component. It can be dynamically changed later by the parent,
|
||||||
@@ -131,7 +131,7 @@ find a template with the component name (or one of its ancestor).
|
|||||||
As such, it should not ever be modified by the component!!
|
As such, it should not ever be modified by the component!!
|
||||||
|
|
||||||
- **`refs`** (Object): the `refs` object contains all references to sub DOM nodes
|
- **`refs`** (Object): the `refs` object contains all references to sub DOM nodes
|
||||||
or sub widgets defined by a `t-ref` directive in the component's template.
|
or sub components defined by a `t-ref` directive in the component's template.
|
||||||
|
|
||||||
### Static Properties
|
### Static Properties
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ find a template with the component name (or one of its ancestor).
|
|||||||
DOM in the same stack frame.
|
DOM in the same stack frame.
|
||||||
|
|
||||||
- **`shouldUpdate(nextProps)`**: this method is called each time a component's props
|
- **`shouldUpdate(nextProps)`**: this method is called each time a component's props
|
||||||
are updated. It returns a boolean, which indicates if the widget should
|
are updated. It returns a boolean, which indicates if the component should
|
||||||
ignore a props update. If it returns false, then `willUpdateProps` will not
|
ignore a props update. If it returns false, then `willUpdateProps` will not
|
||||||
be called, and no rendering will occur. Its default implementation is to
|
be called, and no rendering will occur. Its default implementation is to
|
||||||
always return true. This is an optimization, similar to React's `shouldComponentUpdate`. Most of the time, this should not be used, but it
|
always return true. This is an optimization, similar to React's `shouldComponentUpdate`. Most of the time, this should not be used, but it
|
||||||
@@ -239,7 +239,7 @@ perform some action before the initial rendering of a component.
|
|||||||
|
|
||||||
It will be called exactly once before the initial rendering. It is useful
|
It will be called exactly once before the initial rendering. It is useful
|
||||||
in some cases, for example, to load external assets (such as a JS library)
|
in some cases, for example, to load external assets (such as a JS library)
|
||||||
before the widget is rendered. Another use case is to load data from a server.
|
before the component is rendered. Another use case is to load data from a server.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
async willStart() {
|
async willStart() {
|
||||||
@@ -251,7 +251,7 @@ At this point, the component is not yet rendered. Note that a slow `willStart` m
|
|||||||
interface. Therefore, some care should be made to make this method as
|
interface. Therefore, some care should be made to make this method as
|
||||||
fast as possible.
|
fast as possible.
|
||||||
|
|
||||||
The widget rendering will take place after `willStart` is completed.
|
The component rendering will take place after `willStart` is completed.
|
||||||
|
|
||||||
#### `mounted()`
|
#### `mounted()`
|
||||||
|
|
||||||
@@ -296,8 +296,8 @@ scrollbar.
|
|||||||
|
|
||||||
Note that modifying the state object is not allowed here. This method is called just
|
Note that modifying the state object is not allowed here. This method is called just
|
||||||
before an actual DOM patch, and is only intended to be used to save some local
|
before an actual DOM patch, and is only intended to be used to save some local
|
||||||
DOM state. Also, it will not be called if the widget is not in the DOM (this can
|
DOM state. Also, it will not be called if the component is not in the DOM (this can
|
||||||
happen with widgets with `t-keepalive`).
|
happen with components with `t-keepalive`).
|
||||||
|
|
||||||
The return value of this method will be given as the first argument of the
|
The return value of this method will be given as the first argument of the
|
||||||
corresponding `patched` call.
|
corresponding `patched` call.
|
||||||
@@ -309,12 +309,12 @@ likely via a change in its state/props or environment).
|
|||||||
|
|
||||||
This method is not called on the initial render. It is useful to interact
|
This method is not called on the initial render. It is useful to interact
|
||||||
with the DOM (for example, through an external library) whenever the
|
with the DOM (for example, through an external library) whenever the
|
||||||
component was patched. Note that this hook will not be called if the widget is
|
component was patched. Note that this hook will not be called if the compoent is
|
||||||
not in the DOM (this can happen with widgets with `t-keepalive`).
|
not in the DOM (this can happen with components with `t-keepalive`).
|
||||||
|
|
||||||
The `snapshot` parameter is the result of the previous `willPatch` call.
|
The `snapshot` parameter is the result of the previous `willPatch` call.
|
||||||
|
|
||||||
Updating the widget state in this hook is possible, but not encouraged.
|
Updating the compoent state in this hook is possible, but not encouraged.
|
||||||
One need to be careful, because updates here will cause rerender, which in
|
One need to be careful, because updates here will cause rerender, which in
|
||||||
turn will cause other calls to patched. So, we need to be particularly
|
turn will cause other calls to patched. So, we need to be particularly
|
||||||
careful at avoiding endless cycles.
|
careful at avoiding endless cycles.
|
||||||
@@ -342,78 +342,78 @@ components are declared with a tagname corresponding to the class name. It has
|
|||||||
to be capitalized.
|
to be capitalized.
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<div t-name="ParentWidget">
|
<div t-name="ParentComponent">
|
||||||
<span>some text</span>
|
<span>some text</span>
|
||||||
<MyWidget info="13" />
|
<MyComponent info="13" />
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
class ParentWidget extends owl.Component {
|
class ParentComponent extends owl.Component {
|
||||||
widgets = { MyWidget: MyWidget};
|
components = { MyComponent: MyComponent};
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, the `ParentWidget`'s template creates a widget `MyWidget` just
|
In this example, the `ParentComponent`'s template creates a component `MyComponent` just
|
||||||
after the span. The `info` key will be added to the subwidget's `props`. Each
|
after the span. The `info` key will be added to the subcomponent's `props`. Each
|
||||||
`props` is a string which represents a javascript (QWeb) expression, so it is
|
`props` is a string which represents a javascript (QWeb) expression, so it is
|
||||||
dynamic. If it is necessary to give a string, this can be done by quoting it:
|
dynamic. If it is necessary to give a string, this can be done by quoting it:
|
||||||
`someString="'somevalue'"`.
|
`someString="'somevalue'"`.
|
||||||
|
|
||||||
Note that the rendering context for the template is the widget itself. This means
|
Note that the rendering context for the template is the component itself. This means
|
||||||
that the template can access `state`, `props`, `env`, or any methods defined in the widget.
|
that the template can access `state`, `props`, `env`, or any methods defined in the component.
|
||||||
|
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<div t-name="ParentWidget">
|
<div t-name="ParentComponent">
|
||||||
<ChildWidget count="state.val" />
|
<ChildComponent count="state.val" />
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
class ParentWidget {
|
class ParentComponent {
|
||||||
widgets = { ChildWidget };
|
components = { ChildComponent };
|
||||||
state = { val: 4 };
|
state = { val: 4 };
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Whenever the template is rendered, it will automatically create the subwidget
|
Whenever the template is rendered, it will automatically create the subcomponent
|
||||||
`ChildWidget` at the correct place. It needs to find the reference to the
|
`ChildComponent` at the correct place. It needs to find the reference to the
|
||||||
actual component class in the special `widgets` key, or the class registered in
|
actual component class in the special `components` key, or the class registered in
|
||||||
QWeb's global registry (see `register` function of QWeb). It first looks inside
|
QWeb's global registry (see `register` function of QWeb). It first looks inside
|
||||||
the local `widgets` key, then fallbacks on the global registry.
|
the local `components` key, then fallbacks on the global registry.
|
||||||
|
|
||||||
_Props_: In this example, the child widget will receive the object `{count: 4}` in its
|
_Props_: In this example, the child component will receive the object `{count: 4}` in its
|
||||||
constructor. This will be assigned to the `props` variable, which can be accessed
|
constructor. This will be assigned to the `props` variable, which can be accessed
|
||||||
on the widget (and also, in the template). Whenever the state is updated, then
|
on the component (and also, in the template). Whenever the state is updated, then
|
||||||
the subwidget will also be updated automatically.
|
the sub component will also be updated automatically.
|
||||||
|
|
||||||
Note that there are some restrictions on prop names: `class`, `style` and any
|
Note that there are some restrictions on prop names: `class`, `style` and any
|
||||||
string which starts with `t-` are not allowed.
|
string which starts with `t-` are not allowed.
|
||||||
|
|
||||||
The `t-widget` directive can also be used to accept dynamic values with string interpolation (like the [`t-attf-`](qweb.md#dynamic-attributes) directive):
|
The `t-component` directive can also be used to accept dynamic values with string interpolation (like the [`t-attf-`](qweb.md#dynamic-attributes) directive):
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<div t-name="ParentWidget">
|
<div t-name="ParentComponent">
|
||||||
<t t-widget="ChildWidget{{id}}" />
|
<t t-component="ChildComponent{{id}}" />
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
class ParentWidget {
|
class ParentComponent {
|
||||||
widgets = { ChildWidget1, ChildWidget2 };
|
components = { ChildComponent1, ChildComponent2 };
|
||||||
state = { id: 1 };
|
state = { id: 1 };
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**CSS and style:** there is some specific support to allow the parent to declare
|
**CSS and style:** there is some specific support to allow the parent to declare
|
||||||
additional css classes or style for the sub widget: css declared in `class`, `style`, `t-att-class` or `t-att-style` will be added to the
|
additional css classes or style for the sub component: css declared in `class`, `style`, `t-att-class` or `t-att-style` will be added to the
|
||||||
root widget element.
|
root component element.
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<div t-name="ParentWidget">
|
<div t-name="ParentComponent">
|
||||||
<MyWidget class="someClass" style="font-weight:bold;" info="13" />
|
<MyComponent class="someClass" style="font-weight:bold;" info="13" />
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -425,7 +425,7 @@ class that need to be removed. This is why we only support the explicit syntax
|
|||||||
with a class object:
|
with a class object:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<MyWidget t-att-class="{a: state.flagA, b: state.flagB}" />
|
<MyComponent t-att-class="{a: state.flagA, b: state.flagB}" />
|
||||||
```
|
```
|
||||||
|
|
||||||
### Event Handling
|
### Event Handling
|
||||||
@@ -448,7 +448,7 @@ A _pure_ DOM event is directly triggered by a user interaction (e.g. a `click`).
|
|||||||
This will be roughly translated in javascript like this:
|
This will be roughly translated in javascript like this:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
button.addEventListener("click", widget.someMethod.bind(widget));
|
button.addEventListener("click", component.someMethod.bind(component));
|
||||||
```
|
```
|
||||||
|
|
||||||
The suffix (`click` in this example) is simply the name of the actual DOM
|
The suffix (`click` in this example) is simply the name of the actual DOM
|
||||||
@@ -457,11 +457,11 @@ event.
|
|||||||
A _business_ DOM event is triggered by a call to `trigger` on a component.
|
A _business_ DOM event is triggered by a call to `trigger` on a component.
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<MyWidget t-on-menu-loaded="someMethod" />
|
<MyComponent t-on-menu-loaded="someMethod" />
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
class MyWidget {
|
class MyComponent {
|
||||||
someWhere() {
|
someWhere() {
|
||||||
const payload = ...;
|
const payload = ...;
|
||||||
this.trigger('menu-loaded', payload);
|
this.trigger('menu-loaded', payload);
|
||||||
@@ -471,12 +471,12 @@ A _business_ DOM event is triggered by a call to `trigger` on a component.
|
|||||||
|
|
||||||
The call to `trigger` generates a [_CustomEvent_](https://developer.mozilla.org/docs/Web/Guide/Events/Creating_and_triggering_events)
|
The call to `trigger` generates a [_CustomEvent_](https://developer.mozilla.org/docs/Web/Guide/Events/Creating_and_triggering_events)
|
||||||
of type `menu-loaded` and dispatches it on the component's DOM element
|
of type `menu-loaded` and dispatches it on the component's DOM element
|
||||||
(`this.el`). The event bubbles and is cancelable. The parent widget listening
|
(`this.el`). The event bubbles and is cancelable. The parent component listening
|
||||||
to event `menu-loaded` will receive the payload in its `someMethod` handler
|
to event `menu-loaded` will receive the payload in its `someMethod` handler
|
||||||
(in the `detail` property of the event), whenever the event is triggered.
|
(in the `detail` property of the event), whenever the event is triggered.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
class ParentWidget {
|
class ParentComponent {
|
||||||
someMethod(ev) {
|
someMethod(ev) {
|
||||||
const payload = ev.detail;
|
const payload = ev.detail;
|
||||||
...
|
...
|
||||||
@@ -640,7 +640,7 @@ is inserted into the DOM.
|
|||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
class MyWidget extends owl.Component {
|
class MyComponent extends owl.Component {
|
||||||
...
|
...
|
||||||
focusMe() {
|
focusMe() {
|
||||||
this.refs.someInput.focus();
|
this.refs.someInput.focus();
|
||||||
@@ -671,27 +671,27 @@ component (with some code like `app.mount(document.body)`).
|
|||||||
|
|
||||||
2. when it is done, template `A` is rendered.
|
2. when it is done, template `A` is rendered.
|
||||||
|
|
||||||
- widget `B` is created
|
- component `B` is created
|
||||||
1. `willStart` is called on `B`
|
1. `willStart` is called on `B`
|
||||||
2. template `B` is rendered
|
2. template `B` is rendered
|
||||||
- widget `C` is created
|
- component `C` is created
|
||||||
1. `willStart` is called on `C`
|
1. `willStart` is called on `C`
|
||||||
2. template `C` is rendered
|
2. template `C` is rendered
|
||||||
- widget `D` is created
|
- component `D` is created
|
||||||
1. `willStart` is called on `D`
|
1. `willStart` is called on `D`
|
||||||
2. template `D` is rendered
|
2. template `D` is rendered
|
||||||
- widget `E` is created
|
- component `E` is created
|
||||||
1. `willStart` is called on `E`
|
1. `willStart` is called on `E`
|
||||||
2. template `E` is rendered
|
2. template `E` is rendered
|
||||||
|
|
||||||
3. widget `A` is patched into a detached DOM element. This will create the actual
|
3. component `A` is patched into a detached DOM element. This will create the actual
|
||||||
widget `A` DOM structure. The patching process will cause recursively the
|
component `A` DOM structure. The patching process will cause recursively the
|
||||||
patching of the `B`, `C`, `D` and `E` DOM trees. (so the actual full DOM tree is created
|
patching of the `B`, `C`, `D` and `E` DOM trees. (so the actual full DOM tree is created
|
||||||
in one pass)
|
in one pass)
|
||||||
|
|
||||||
4. the widget `A` root element is actually appended to `document.body`
|
4. the component `A` root element is actually appended to `document.body`
|
||||||
|
|
||||||
5. The method `mounted` is called recursively on all widgets in the following
|
5. The method `mounted` is called recursively on all components in the following
|
||||||
order: `B`, `D`, `E`, `C`, `A`.
|
order: `B`, `D`, `E`, `C`, `A`.
|
||||||
|
|
||||||
**Scenario 2: rerendering a component**. Now, let's assume that the user clicked on some
|
**Scenario 2: rerendering a component**. Now, let's assume that the user clicked on some
|
||||||
@@ -699,7 +699,7 @@ button in `C`, and this results in a state update, which is supposed to:
|
|||||||
|
|
||||||
- update `D`,
|
- update `D`,
|
||||||
- remove `E`,
|
- remove `E`,
|
||||||
- add new widget `F`.
|
- add new component `F`.
|
||||||
|
|
||||||
So, the component tree should look like this:
|
So, the component tree should look like this:
|
||||||
|
|
||||||
@@ -716,17 +716,17 @@ Here is what Owl will do:
|
|||||||
1. because of a state change, the method `render` is called on `C`
|
1. because of a state change, the method `render` is called on `C`
|
||||||
2. template `C` is rendered again
|
2. template `C` is rendered again
|
||||||
|
|
||||||
- widget `D` is updated:
|
- component `D` is updated:
|
||||||
1. hook `willUpdateProps` is called on `D` (async)
|
1. hook `willUpdateProps` is called on `D` (async)
|
||||||
2. template `D` is rerendered
|
2. template `D` is rerendered
|
||||||
- widget `F` is created:
|
- component `F` is created:
|
||||||
1. hook `willStart` is called on `E` (async)
|
1. hook `willStart` is called on `E` (async)
|
||||||
2. template `F` is rendered
|
2. template `F` is rendered
|
||||||
|
|
||||||
3. `willPatch` hooks are called recursively on widgets `C`, `D` (not on `F`,
|
3. `willPatch` hooks are called recursively on components `C`, `D` (not on `F`,
|
||||||
because it is not mounted yet)
|
because it is not mounted yet)
|
||||||
|
|
||||||
4. widget `C` is patched, which will cause recursively:
|
4. component `C` is patched, which will cause recursively:
|
||||||
|
|
||||||
2. `willUnmount` hook on `E`, then destruction of `E`,
|
2. `willUnmount` hook on `E`, then destruction of `E`,
|
||||||
3. (initial) patching of `F`, then hook `mounted` is called on `F`
|
3. (initial) patching of `F`, then hook `mounted` is called on `F`
|
||||||
@@ -830,42 +830,42 @@ Like the `t-on` directive, it can work either on a DOM node, or on a component:
|
|||||||
```xml
|
```xml
|
||||||
<div>
|
<div>
|
||||||
<div t-ref="someDiv"/>
|
<div t-ref="someDiv"/>
|
||||||
<SubWidget t-ref="someWidget"/>
|
<SubComponent t-ref="someComponent"/>
|
||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, the widget will be able to access the `div` and the component
|
In this example, the component will be able to access the `div` and the component
|
||||||
inside the special `refs` variable:
|
inside the special `refs` variable:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
this.refs.someDiv;
|
this.refs.someDiv;
|
||||||
this.refs.someWidget;
|
this.refs.someComponent;
|
||||||
```
|
```
|
||||||
|
|
||||||
This is useful for various usecases: for example, integrating with an external
|
This is useful for various usecases: for example, integrating with an external
|
||||||
library that needs to render itself inside an actual DOM node. Or for calling
|
library that needs to render itself inside an actual DOM node. Or for calling
|
||||||
some method on a sub widget.
|
some method on a sub component.
|
||||||
|
|
||||||
Note: if used on a component, the reference will be set in the `refs`
|
Note: if used on a component, the reference will be set in the `refs`
|
||||||
variable between `willPatch` and `patched`.
|
variable between `willPatch` and `patched`.
|
||||||
|
|
||||||
The `t-ref` directive also accepts dynamic values with string interpolation
|
The `t-ref` directive also accepts dynamic values with string interpolation
|
||||||
(like the [`t-attf-`](qweb.md#dynamic-attributes) and
|
(like the [`t-attf-`](qweb.md#dynamic-attributes) and
|
||||||
`t-widget` directives). For example, if we have
|
`t-component` directives). For example, if we have
|
||||||
`id` set to 44 in the rendering context,
|
`id` set to 44 in the rendering context,
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<div t-ref="widget_{{id}}"/>
|
<div t-ref="component_{{id}}"/>
|
||||||
```
|
```
|
||||||
|
|
||||||
```js
|
```js
|
||||||
this.refs.widget_44;
|
this.refs.component_44;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Slots
|
### Slots
|
||||||
|
|
||||||
To make generic components, it is useful to be able for a parent widget to _inject_
|
To make generic components, it is useful to be able for a parent component to _inject_
|
||||||
some sub template, but still be the owner. For example, a generic dialog widget
|
some sub template, but still be the owner. For example, a generic dialog component
|
||||||
will need to render some content, some footer, but with the parent as the
|
will need to render some content, some footer, but with the parent as the
|
||||||
rendering context.
|
rendering context.
|
||||||
|
|
||||||
@@ -886,8 +886,8 @@ This is what _slots_ are for.
|
|||||||
Slots are defined by the caller, with the `t-set` directive:
|
Slots are defined by the caller, with the `t-set` directive:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<div t-name="SomeWidget">
|
<div t-name="SomeComponent">
|
||||||
<div>some widget</div>
|
<div>some component</div>
|
||||||
<Dialog title="Some Dialog">
|
<Dialog title="Some Dialog">
|
||||||
<t t-set="content">
|
<t t-set="content">
|
||||||
<div>hey</div>
|
<div>hey</div>
|
||||||
@@ -899,7 +899,7 @@ Slots are defined by the caller, with the `t-set` directive:
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
In this example, the widget `Dialog` will render the slots `content` and `footer`
|
In this example, the component `Dialog` will render the slots `content` and `footer`
|
||||||
with its parent as rendering context. This means that clicking on the button
|
with its parent as rendering context. This means that clicking on the button
|
||||||
will execute the `doSomething` method on the parent, not on the dialog.
|
will execute the `doSomething` method on the parent, not on the dialog.
|
||||||
|
|
||||||
@@ -922,7 +922,7 @@ is not allowed. A workaround could be to wrap the content in a div:
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
Default slot: the first element inside the widget which is not a named slot will
|
Default slot: the first element inside the component which is not a named slot will
|
||||||
be considered the `default` slot. For example:
|
be considered the `default` slot. For example:
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
@@ -946,23 +946,23 @@ components.
|
|||||||
|
|
||||||
There are two different common problems with Owl asynchronous rendering model:
|
There are two different common problems with Owl asynchronous rendering model:
|
||||||
|
|
||||||
- any widget can delay the rendering (initial and subsequent) of the whole
|
- any component can delay the rendering (initial and subsequent) of the whole
|
||||||
application
|
application
|
||||||
- for a given widget, there are two independant situations that will trigger an
|
- for a given component, there are two independant situations that will trigger an
|
||||||
asynchronous rerendering: a change in the state, or a change in the props.
|
asynchronous rerendering: a change in the state, or a change in the props.
|
||||||
These changes may be done at different times, and Owl has no way of knowing
|
These changes may be done at different times, and Owl has no way of knowing
|
||||||
how to reconcile the resulting renderings.
|
how to reconcile the resulting renderings.
|
||||||
|
|
||||||
Here are a few tips on how to work with asynchronous widgets:
|
Here are a few tips on how to work with asynchronous components:
|
||||||
|
|
||||||
1. Minimize the use of asynchronous widgets!
|
1. Minimize the use of asynchronous components!
|
||||||
2. Maybe move the asynchronous logic in a store, which then triggers (mostly)
|
2. Maybe move the asynchronous logic in a store, which then triggers (mostly)
|
||||||
synchronous renderings
|
synchronous renderings
|
||||||
3. Lazy loading external libraries is a good use case for async rendering. This
|
3. Lazy loading external libraries is a good use case for async rendering. This
|
||||||
is mostly fine, because we can assume that it will only takes a fraction of a
|
is mostly fine, because we can assume that it will only takes a fraction of a
|
||||||
second, and only once (see `owl.utils.loadJS`)
|
second, and only once (see `owl.utils.loadJS`)
|
||||||
4. For all the other cases, the `t-asyncroot` directive (to use alongside
|
4. For all the other cases, the `t-asyncroot` directive (to use alongside
|
||||||
`t-widget`) is there to help you. When this directive is met, a new rendering
|
`t-component`) is there to help you. When this directive is met, a new rendering
|
||||||
sub tree is created, such that the rendering of that component (and its
|
sub tree is created, such that the rendering of that component (and its
|
||||||
children) is not tied to the rendering of the rest of the interface. It can
|
children) is not tied to the rendering of the rest of the interface. It can
|
||||||
be used on an asynchronous component, to prevent it from delaying the
|
be used on an asynchronous component, to prevent it from delaying the
|
||||||
@@ -972,7 +972,7 @@ Here are a few tips on how to work with asynchronous widgets:
|
|||||||
(triggered by state or props changes).
|
(triggered by state or props changes).
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<div t-name="ParentWidget">
|
<div t-name="ParentComponent">
|
||||||
<SyncChild />
|
<SyncChild />
|
||||||
<AsyncChild t-asyncroot="1"/>
|
<AsyncChild t-asyncroot="1"/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+4
-4
@@ -58,16 +58,16 @@ To build an application (or a sub-part of an application), we need two things:
|
|||||||
need. In practice, it could context some user session information, some
|
need. In practice, it could context some user session information, some
|
||||||
configuration keys (for example, isMobile = true/false if we are in mobile mode).
|
configuration keys (for example, isMobile = true/false if we are in mobile mode).
|
||||||
|
|
||||||
- a description of the user interface: there should be a root widget, which can
|
- a description of the user interface: there should be a root component, which can
|
||||||
have sub widgets
|
have sub components
|
||||||
|
|
||||||
Here are a few steps that we may take to get started:
|
Here are a few steps that we may take to get started:
|
||||||
|
|
||||||
- get the templates
|
- get the templates
|
||||||
- create a qweb engine, with the templates
|
- create a qweb engine, with the templates
|
||||||
- create an environment
|
- create an environment
|
||||||
- create an instance of the root widget
|
- create an instance of the root component
|
||||||
- mount the root widget to a DOM element
|
- mount the root component to a DOM element
|
||||||
|
|
||||||
Let us now add the javascript to make it work, in `app.js`:
|
Let us now add the javascript to make it work, in `app.js`:
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -44,7 +44,7 @@ with a few interesting points:
|
|||||||
|
|
||||||
- it compiles templates into functions that output a virtual DOM instead of a
|
- it compiles templates into functions that output a virtual DOM instead of a
|
||||||
string. This is necessary for the component system.
|
string. This is necessary for the component system.
|
||||||
- it has a few extra directives: `t-widget`, `t-on`, ...
|
- it has a few extra directives: `t-component`, `t-on`, ...
|
||||||
|
|
||||||
## Directives
|
## Directives
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ needs. Here is a list of all Owl specific directives:
|
|||||||
|
|
||||||
| Name | Description |
|
| Name | Description |
|
||||||
| -------------------------------------------- | ----------------------------------------------------------------------------------- |
|
| -------------------------------------------- | ----------------------------------------------------------------------------------- |
|
||||||
| `t-widget`, `t-keepalive`, `t-asyncroot` | [Defining a sub component](component.md#composition) |
|
| `t-component`, `t-keepalive`, `t-asyncroot` | [Defining a sub component](component.md#composition) |
|
||||||
| `t-ref` | [Setting a reference to a dom node or a sub component](component.md#references) |
|
| `t-ref` | [Setting a reference to a dom node or a sub component](component.md#references) |
|
||||||
| `t-key` | [Defining a key (to help virtual dom reconciliation)](component.md#t-key-directive) |
|
| `t-key` | [Defining a key (to help virtual dom reconciliation)](component.md#t-key-directive) |
|
||||||
| `t-on-*` | [Event handling](component.md#event-handling) |
|
| `t-on-*` | [Event handling](component.md#event-handling) |
|
||||||
@@ -108,7 +108,7 @@ It's API is quite simple:
|
|||||||
const TEMPLATES = `
|
const TEMPLATES = `
|
||||||
<templates>
|
<templates>
|
||||||
<div t-name="App" class="main">main</div>
|
<div t-name="App" class="main">main</div>
|
||||||
<div t-name="OtherWidget">other widget</div>
|
<div t-name="OtherComponent">other component</div>
|
||||||
</templates>`;
|
</templates>`;
|
||||||
qweb.addTemplates(TEMPLATES);
|
qweb.addTemplates(TEMPLATES);
|
||||||
```
|
```
|
||||||
@@ -117,12 +117,12 @@ It's API is quite simple:
|
|||||||
which is a virtual representation of the DOM (see [vdom doc](vdom.md)).
|
which is a virtual representation of the DOM (see [vdom doc](vdom.md)).
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const vnode = qweb.render("App", widget);
|
const vnode = qweb.render("App", component);
|
||||||
```
|
```
|
||||||
|
|
||||||
- **`register(name, Component)`**: static function to register an OWL Component
|
- **`register(name, Component)`**: static function to register an OWL Component
|
||||||
to QWeb's global registry. Globally registered Components can be used in
|
to QWeb's global registry. Globally registered Components can be used in
|
||||||
templates (see the `t-widget` directive). This is useful for commonly used
|
templates (see the `t-component` directive). This is useful for commonly used
|
||||||
components accross the application.
|
components accross the application.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -131,8 +131,8 @@ It's API is quite simple:
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
class ParentWidget extends owl.Component { ... }
|
class ParentComponent extends owl.Component { ... }
|
||||||
qweb.addTemplate("ParentWidget", "<div><Dialog/></div>");
|
qweb.addTemplate("ParentComponent", "<div><Dialog/></div>");
|
||||||
```
|
```
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
@@ -179,7 +179,7 @@ root nodes.
|
|||||||
|
|
||||||
QWeb expressions are strings that will be processed at compile time. Each variable in
|
QWeb expressions are strings that will be processed at compile time. Each variable in
|
||||||
the javascript expression will be replaced by a lookup in the context (so, the
|
the javascript expression will be replaced by a lookup in the context (so, the
|
||||||
widget). For example, `a + b.c(d)` will be converted into:
|
component). For example, `a + b.c(d)` will be converted into:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
context["a"] + context["b"].c(context["d"]);
|
context["a"] + context["b"].c(context["d"]);
|
||||||
|
|||||||
+27
-27
@@ -42,8 +42,8 @@ export interface Meta<T extends Env, Props> {
|
|||||||
isDestroyed: boolean;
|
isDestroyed: boolean;
|
||||||
parent: Component<T, any, any> | null;
|
parent: Component<T, any, any> | null;
|
||||||
children: { [key: number]: Component<T, any, any> };
|
children: { [key: number]: Component<T, any, any> };
|
||||||
// children mapping: from templateID to widgetID
|
// children mapping: from templateID to componentID
|
||||||
// should it be a map number => Widget?
|
// should it be a map number => Component?
|
||||||
cmap: { [key: number]: number };
|
cmap: { [key: number]: number };
|
||||||
|
|
||||||
renderId: number;
|
renderId: number;
|
||||||
@@ -62,7 +62,7 @@ export interface Meta<T extends Env, Props> {
|
|||||||
const TEMPLATE_MAP: { [key: number]: { [name: string]: string } } = {};
|
const TEMPLATE_MAP: { [key: number]: { [name: string]: string } } = {};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Widget
|
// Component
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
let nextId = 1;
|
let nextId = 1;
|
||||||
|
|
||||||
@@ -71,8 +71,8 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
template?: string;
|
template?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `el` is the root element of the widget. Note that it could be null:
|
* The `el` is the root element of the component. Note that it could be null:
|
||||||
* this is the case if the widget is not mounted yet, or is destroyed.
|
* this is the case if the component is not mounted yet, or is destroyed.
|
||||||
*/
|
*/
|
||||||
get el(): HTMLElement | null {
|
get el(): HTMLElement | null {
|
||||||
return this.__owl__.vnode ? (<any>this).__owl__.vnode.elm : null;
|
return this.__owl__.vnode ? (<any>this).__owl__.vnode.elm : null;
|
||||||
@@ -97,21 +97,21 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
/**
|
/**
|
||||||
* Creates an instance of Component.
|
* Creates an instance of Component.
|
||||||
*
|
*
|
||||||
* The root widget of a component tree needs an environment:
|
* The root component of a component tree needs an environment:
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* const root = new RootWidget(env, props);
|
* const root = new RootComponent(env, props);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Every other widget simply needs a reference to its parent:
|
* Every other component simply needs a reference to its parent:
|
||||||
*
|
*
|
||||||
* ```javascript
|
* ```javascript
|
||||||
* const child = new SomeWidget(parent, props);
|
* const child = new SomeComponent(parent, props);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Note that most of the time, only the root widget needs to be created by
|
* Note that most of the time, only the root component needs to be created by
|
||||||
* hand. Other widgets should be created automatically by the framework (with
|
* hand. Other components should be created automatically by the framework (with
|
||||||
* the t-widget directive in a template)
|
* the t-component directive in a template)
|
||||||
*/
|
*/
|
||||||
constructor(parent: Component<T, any, any> | T, props?: Props) {
|
constructor(parent: Component<T, any, any> | T, props?: Props) {
|
||||||
const defaultProps = (<any>this.constructor).defaultProps;
|
const defaultProps = (<any>this.constructor).defaultProps;
|
||||||
@@ -122,9 +122,9 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
this._validateProps(props || {});
|
this._validateProps(props || {});
|
||||||
}
|
}
|
||||||
// is this a good idea?
|
// is this a good idea?
|
||||||
// Pro: if props is empty, we can create easily a widget
|
// Pro: if props is empty, we can create easily a component
|
||||||
// Con: this is not really safe
|
// Con: this is not really safe
|
||||||
// Pro: but creating widget (by a template) is always unsafe anyway
|
// Pro: but creating component (by a template) is always unsafe anyway
|
||||||
this.props = <Props>props || <Props>{};
|
this.props = <Props>props || <Props>{};
|
||||||
let id: number = nextId++;
|
let id: number = nextId++;
|
||||||
let p: Component<T, any, any> | null = null;
|
let p: Component<T, any, any> | null = null;
|
||||||
@@ -157,7 +157,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
*
|
*
|
||||||
* It will be called exactly once before the initial rendering. It is useful
|
* It will be called exactly once before the initial rendering. It is useful
|
||||||
* in some cases, for example, to load external assets (such as a JS library)
|
* in some cases, for example, to load external assets (such as a JS library)
|
||||||
* before the widget is rendered.
|
* before the component is rendered.
|
||||||
*
|
*
|
||||||
* Note that a slow willStart method will slow down the rendering of the user
|
* Note that a slow willStart method will slow down the rendering of the user
|
||||||
* interface. Therefore, some effort should be made to make this method as
|
* interface. Therefore, some effort should be made to make this method as
|
||||||
@@ -207,7 +207,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
* with the DOM (for example, through an external library) whenever the
|
* with the DOM (for example, through an external library) whenever the
|
||||||
* component was updated.
|
* component was updated.
|
||||||
*
|
*
|
||||||
* Updating the widget state in this hook is possible, but not encouraged.
|
* Updating the component state in this hook is possible, but not encouraged.
|
||||||
* One need to be careful, because updates here will cause rerender, which in
|
* One need to be careful, because updates here will cause rerender, which in
|
||||||
* turn will cause other calls to updated. So, we need to be particularly
|
* turn will cause other calls to updated. So, we need to be particularly
|
||||||
* careful at avoiding endless cycles.
|
* careful at avoiding endless cycles.
|
||||||
@@ -284,8 +284,8 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
* - call the willUnmount hooks if necessary
|
* - call the willUnmount hooks if necessary
|
||||||
* - remove the dom node from the dom
|
* - remove the dom node from the dom
|
||||||
*
|
*
|
||||||
* This should only be called manually if you created the widget. Most widgets
|
* This should only be called manually if you created the component. Most
|
||||||
* will be automatically destroyed.
|
* components will be automatically destroyed.
|
||||||
*/
|
*/
|
||||||
destroy() {
|
destroy() {
|
||||||
const __owl__ = this.__owl__;
|
const __owl__ = this.__owl__;
|
||||||
@@ -308,8 +308,8 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is the correct way to update the environment of a widget. Doing
|
* This method is the correct way to update the environment of a component. Doing
|
||||||
* this will cause a full rerender of the widget and its children, so this is
|
* this will cause a full rerender of the component and its children, so this is
|
||||||
* an operation that should not be done frequently.
|
* an operation that should not be done frequently.
|
||||||
*
|
*
|
||||||
* A good usecase for updating the environment would be to update some mostly
|
* A good usecase for updating the environment would be to update some mostly
|
||||||
@@ -499,9 +499,9 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this part is critical for the patching process to be done correctly. The
|
// this part is critical for the patching process to be done correctly. The
|
||||||
// tricky part is that a child widget can be rerendered on its own, which
|
// tricky part is that a child component can be rerendered on its own, which
|
||||||
// will update its own vnode representation without the knowledge of the
|
// will update its own vnode representation without the knowledge of the
|
||||||
// parent widget. With this, we make sure that the parent widget will be
|
// parent component. With this, we make sure that the parent component will be
|
||||||
// able to patch itself properly after
|
// able to patch itself properly after
|
||||||
vnode.key = __owl__.id;
|
vnode.key = __owl__.id;
|
||||||
__owl__.renderProps = this.props;
|
__owl__.renderProps = this.props;
|
||||||
@@ -510,7 +510,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only called by qweb t-widget directive
|
* Only called by qweb t-component directive
|
||||||
*/
|
*/
|
||||||
_mount(vnode: VNode, elm: HTMLElement): VNode {
|
_mount(vnode: VNode, elm: HTMLElement): VNode {
|
||||||
const __owl__ = this.__owl__;
|
const __owl__ = this.__owl__;
|
||||||
@@ -522,7 +522,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only called by qweb t-widget directive (when t-keepalive is set)
|
* Only called by qweb t-component directive (when t-keepalive is set)
|
||||||
*/
|
*/
|
||||||
_remount() {
|
_remount() {
|
||||||
const __owl__ = this.__owl__;
|
const __owl__ = this.__owl__;
|
||||||
@@ -593,7 +593,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
for (let i = 0, l = propsDef.length; i < l; i++) {
|
for (let i = 0, l = propsDef.length; i < l; i++) {
|
||||||
if (!(propsDef[i] in props)) {
|
if (!(propsDef[i] in props)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Missing props '${propsDef[i]}' (widget '${this.constructor.name}')`
|
`Missing props '${propsDef[i]}' (component '${this.constructor.name}')`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -603,7 +603,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
if (!(propName in props)) {
|
if (!(propName in props)) {
|
||||||
if (propsDef[propName] && !propsDef[propName].optional) {
|
if (propsDef[propName] && !propsDef[propName].optional) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Missing props '${propName}' (widget '${this.constructor.name}')`
|
`Missing props '${propName}' (component '${this.constructor.name}')`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -612,7 +612,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
|
|||||||
let isValid = isValidProp(props[propName], propsDef[propName]);
|
let isValid = isValidProp(props[propName], propsDef[propName]);
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Props '${propName}' of invalid type in widget '${
|
`Props '${propName}' of invalid type in component '${
|
||||||
this.constructor.name
|
this.constructor.name
|
||||||
}'`
|
}'`
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ export class EventBus {
|
|||||||
* Add a listener for the 'eventType' events.
|
* Add a listener for the 'eventType' events.
|
||||||
*
|
*
|
||||||
* Note that the 'owner' of this event can be anything, but will more likely
|
* Note that the 'owner' of this event can be anything, but will more likely
|
||||||
* be a widget or a class. The idea is that the callback will be called with
|
* be a component or a class. The idea is that the callback will be called with
|
||||||
* the proper owner bound.
|
* the proper owner bound.
|
||||||
*
|
*
|
||||||
* Also, the owner should be kind of unique. This will be used to remove the
|
* Also, the owner should be kind of unique. This will be used to remove the
|
||||||
|
|||||||
+6
-6
@@ -130,7 +130,7 @@ let nextID = 1;
|
|||||||
export class QWeb {
|
export class QWeb {
|
||||||
templates: { [name: string]: Template } = {};
|
templates: { [name: string]: Template } = {};
|
||||||
utils = UTILS;
|
utils = UTILS;
|
||||||
static widgets = Object.create(null);
|
static components = Object.create(null);
|
||||||
|
|
||||||
// dev mode enables better error messages or more costly validations
|
// dev mode enables better error messages or more costly validations
|
||||||
static dev: boolean = false;
|
static dev: boolean = false;
|
||||||
@@ -140,7 +140,7 @@ export class QWeb {
|
|||||||
// able to map a qweb instance to a template name.
|
// able to map a qweb instance to a template name.
|
||||||
id = nextID++;
|
id = nextID++;
|
||||||
|
|
||||||
// slots contains sub templates defined with t-set inside t-widget nodes, and
|
// slots contains sub templates defined with t-set inside t-component nodes, and
|
||||||
// are meant to be used by the t-slot directive.
|
// are meant to be used by the t-slot directive.
|
||||||
slots = {};
|
slots = {};
|
||||||
nextSlotId = 1;
|
nextSlotId = 1;
|
||||||
@@ -161,10 +161,10 @@ export class QWeb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static register(name: string, Component: any) {
|
static register(name: string, Component: any) {
|
||||||
if (QWeb.widgets[name]) {
|
if (QWeb.components[name]) {
|
||||||
throw new Error(`Component '${name}' has already been registered`);
|
throw new Error(`Component '${name}' has already been registered`);
|
||||||
}
|
}
|
||||||
QWeb.widgets[name] = Component;
|
QWeb.components[name] = Component;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -349,8 +349,8 @@ export class QWeb {
|
|||||||
const firstLetter = node.tagName[0];
|
const firstLetter = node.tagName[0];
|
||||||
if (firstLetter === firstLetter.toUpperCase()) {
|
if (firstLetter === firstLetter.toUpperCase()) {
|
||||||
// this is a component, we modify in place the xml document to change
|
// this is a component, we modify in place the xml document to change
|
||||||
// <SomeComponent ... /> to <t t-widget="SomeComponent" ... />
|
// <SomeComponent ... /> to <t t-component="SomeComponent" ... />
|
||||||
node.setAttribute('t-widget', node.tagName);
|
node.setAttribute('t-component', node.tagName);
|
||||||
node.nodeValue = 't';
|
node.nodeValue = 't';
|
||||||
}
|
}
|
||||||
const attributes = (<Element>node).attributes;
|
const attributes = (<Element>node).attributes;
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ QWeb.addDirective({
|
|||||||
let shouldWarn =
|
let shouldWarn =
|
||||||
nodeCopy.tagName !== "t" && !nodeCopy.hasAttribute("t-key");
|
nodeCopy.tagName !== "t" && !nodeCopy.hasAttribute("t-key");
|
||||||
if (!shouldWarn && node.tagName === "t") {
|
if (!shouldWarn && node.tagName === "t") {
|
||||||
if (node.hasAttribute("t-widget") && !node.hasAttribute("t-key")) {
|
if (node.hasAttribute("t-component") && !node.hasAttribute("t-key")) {
|
||||||
shouldWarn = true;
|
shouldWarn = true;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
|||||||
+71
-71
@@ -10,7 +10,7 @@ import { VNode } from "./vdom";
|
|||||||
* - t-on
|
* - t-on
|
||||||
* - t-ref
|
* - t-ref
|
||||||
* - t-transition
|
* - t-transition
|
||||||
* - t-widget/t-keepalive
|
* - t-component/t-keepalive
|
||||||
* - t-mounted
|
* - t-mounted
|
||||||
* - t-slot
|
* - t-slot
|
||||||
* - t-model
|
* - t-model
|
||||||
@@ -191,21 +191,21 @@ QWeb.addDirective({
|
|||||||
});
|
});
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// t-widget
|
// t-component
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
const T_COMPONENT_MODS_CODE = Object.assign({}, MODS_CODE, {
|
||||||
self: "if (e.target !== vn.elm) {return}"
|
self: "if (e.target !== vn.elm) {return}"
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The t-widget directive is certainly a complicated and hard to maintain piece
|
* The t-component directive is certainly a complicated and hard to maintain piece
|
||||||
* of code. To help you, fellow developer, if you have to maintain it, I offer
|
* of code. To help you, fellow developer, if you have to maintain it, I offer
|
||||||
* you this advice: Good luck...
|
* you this advice: Good luck...
|
||||||
*
|
*
|
||||||
* Since it is not 'direct' code, but rather code that generates other code, it
|
* Since it is not 'direct' code, but rather code that generates other code, it
|
||||||
* is not easy to understand. To help you, here is a detailed and commented
|
* is not easy to understand. To help you, here is a detailed and commented
|
||||||
* explanation of the code generated by the t-widget directive for the following
|
* explanation of the code generated by the t-component directive for the following
|
||||||
* situation:
|
* situation:
|
||||||
* ```xml
|
* ```xml
|
||||||
* <Child
|
* <Child
|
||||||
@@ -216,23 +216,23 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
|||||||
*
|
*
|
||||||
* ```js
|
* ```js
|
||||||
* // we assign utils on top of the function because it will be useful for
|
* // we assign utils on top of the function because it will be useful for
|
||||||
* // each widgets
|
* // each components
|
||||||
* let utils = this.utils;
|
* let utils = this.utils;
|
||||||
*
|
*
|
||||||
* // this is the virtual node representing the parent div
|
* // this is the virtual node representing the parent div
|
||||||
* let c1 = [], p1 = { key: 1 };
|
* let c1 = [], p1 = { key: 1 };
|
||||||
* var vn1 = h("div", p1, c1);
|
* var vn1 = h("div", p1, c1);
|
||||||
*
|
*
|
||||||
* // t-widget directive: we start by evaluating the expression given by t-key:
|
* // t-component directive: we start by evaluating the expression given by t-key:
|
||||||
* let key5 = "somestring";
|
* let key5 = "somestring";
|
||||||
*
|
*
|
||||||
* // def3 is the promise that will contain later either the new widget
|
* // def3 is the promise that will contain later either the new component
|
||||||
* // creation, or the props update...
|
* // creation, or the props update...
|
||||||
* let def3;
|
* let def3;
|
||||||
*
|
*
|
||||||
* // this is kind of tricky: we need here to find if the widget was already
|
* // this is kind of tricky: we need here to find if the component was already
|
||||||
* // created by a previous rendering. This is done by checking the internal
|
* // created by a previous rendering. This is done by checking the internal
|
||||||
* // `cmap` (children map) of the parent widget: it maps keys to widget ids,
|
* // `cmap` (children map) of the parent component: it maps keys to component ids,
|
||||||
* // and, then, if there is an id, we look into the children list to get the
|
* // and, then, if there is an id, we look into the children list to get the
|
||||||
* // instance
|
* // instance
|
||||||
* let w4 =
|
* let w4 =
|
||||||
@@ -240,9 +240,9 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
|||||||
* ? context.__owl__.children[context.__owl__.cmap[key5]]
|
* ? context.__owl__.children[context.__owl__.cmap[key5]]
|
||||||
* : false;
|
* : false;
|
||||||
*
|
*
|
||||||
* // We keep the index of the position of the widget in the closure. We push
|
* // We keep the index of the position of the component in the closure. We push
|
||||||
* // null to reserve the slot, and will replace it later by the widget vnode,
|
* // null to reserve the slot, and will replace it later by the component vnode,
|
||||||
* // when it will be ready (do not forget that preparing/rendering a widget is
|
* // when it will be ready (do not forget that preparing/rendering a component is
|
||||||
* // asynchronous)
|
* // asynchronous)
|
||||||
* let _2_index = c1.length;
|
* let _2_index = c1.length;
|
||||||
* c1.push(null);
|
* c1.push(null);
|
||||||
@@ -252,7 +252,7 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
|||||||
* // computation, so it is certainly better to do it only once
|
* // computation, so it is certainly better to do it only once
|
||||||
* let props4 = { flag: context["state"].flag };
|
* let props4 = { flag: context["state"].flag };
|
||||||
*
|
*
|
||||||
* // If we have a widget, currently rendering, but not ready yet, we do not want
|
* // If we have a component, currently rendering, but not ready yet, we do not want
|
||||||
* // to wait for it to be ready if we can avoid it
|
* // to wait for it to be ready if we can avoid it
|
||||||
* if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) {
|
* if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) {
|
||||||
* // we check if the props are the same. In that case, we can simply reuse
|
* // we check if the props are the same. In that case, we can simply reuse
|
||||||
@@ -260,7 +260,7 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
|||||||
* if (utils.shallowEqual(props4, w4.__owl__.renderProps)) {
|
* if (utils.shallowEqual(props4, w4.__owl__.renderProps)) {
|
||||||
* def3 = w4.__owl__.renderPromise;
|
* def3 = w4.__owl__.renderPromise;
|
||||||
* } else {
|
* } else {
|
||||||
* // if the props are not the same, we destroy the widget and starts anew.
|
* // if the props are not the same, we destroy the component and starts anew.
|
||||||
* // this will be faster than waiting for its rendering, then updating it
|
* // this will be faster than waiting for its rendering, then updating it
|
||||||
* w4.destroy();
|
* w4.destroy();
|
||||||
* w4 = false;
|
* w4 = false;
|
||||||
@@ -268,29 +268,29 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* if (!w4) {
|
* if (!w4) {
|
||||||
* // in this situation, we need to create a new widget. First step is
|
* // in this situation, we need to create a new component. First step is
|
||||||
* // to get a reference to the class, then create an instance with
|
* // to get a reference to the class, then create an instance with
|
||||||
* // current context as parent, and the props.
|
* // current context as parent, and the props.
|
||||||
* let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
* let W4 = context.component && context.components[componentKey4] || QWeb.component[componentKey4];
|
||||||
|
|
||||||
* if (!W4) {
|
* if (!W4) {
|
||||||
* throw new Error("Cannot find the definition of widget 'child'");
|
* throw new Error("Cannot find the definition of component 'child'");
|
||||||
* }
|
* }
|
||||||
* w4 = new W4(owner, props4);
|
* w4 = new W4(owner, props4);
|
||||||
*
|
*
|
||||||
* // Whenever we rerender the parent widget, we need to be sure that we
|
* // Whenever we rerender the parent component, we need to be sure that we
|
||||||
* // are able to find the widget instance. To do that, we register it to
|
* // are able to find the component instance. To do that, we register it to
|
||||||
* // the parent cmap (children map). Note that the 'template' key is
|
* // the parent cmap (children map). Note that the 'template' key is
|
||||||
* // used here, since this is what identify the widget from the template
|
* // used here, since this is what identify the component from the template
|
||||||
* // perspective.
|
* // perspective.
|
||||||
* context.__owl__.cmap[key5] = w4.__owl__.id;
|
* context.__owl__.cmap[key5] = w4.__owl__.id;
|
||||||
*
|
*
|
||||||
* // _prepare is called, to basically call willStart, then render the
|
* // _prepare is called, to basically call willStart, then render the
|
||||||
* // widget
|
* // component
|
||||||
* def3 = w4._prepare();
|
* def3 = w4._prepare();
|
||||||
*
|
*
|
||||||
* def3 = def3.then(vnode => {
|
* def3 = def3.then(vnode => {
|
||||||
* // we create here a virtual node for the parent (NOT the widget). This
|
* // we create here a virtual node for the parent (NOT the component). This
|
||||||
* // means that the vdom of the parent will be stopped here, and from
|
* // means that the vdom of the parent will be stopped here, and from
|
||||||
* // the parent's perspective, it simply is a vnode with no children.
|
* // the parent's perspective, it simply is a vnode with no children.
|
||||||
* // However, it shares the same dom element with the component root
|
* // However, it shares the same dom element with the component root
|
||||||
@@ -298,16 +298,16 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
|||||||
* let pvnode = h(vnode.sel, { key: key5 });
|
* let pvnode = h(vnode.sel, { key: key5 });
|
||||||
*
|
*
|
||||||
* // we add hooks to the parent vnode so we can interact with the new
|
* // we add hooks to the parent vnode so we can interact with the new
|
||||||
* // widget at the proper time
|
* // component at the proper time
|
||||||
* pvnode.data.hook = {
|
* pvnode.data.hook = {
|
||||||
* insert(vn) {
|
* insert(vn) {
|
||||||
* // the _mount method will patch the widget vdom into the elm vn.elm,
|
* // the _mount method will patch the component vdom into the elm vn.elm,
|
||||||
* // then call the mounted hooks. However, suprisingly, the snabbdom
|
* // then call the mounted hooks. However, suprisingly, the snabbdom
|
||||||
* // patch method actually replace the elm by a new elm, so we need
|
* // patch method actually replace the elm by a new elm, so we need
|
||||||
* // to synchronise the pvnode elm with the resulting elm
|
* // to synchronise the pvnode elm with the resulting elm
|
||||||
* let nvn = w4._mount(vnode, vn.elm);
|
* let nvn = w4._mount(vnode, vn.elm);
|
||||||
* pvnode.elm = nvn.elm;
|
* pvnode.elm = nvn.elm;
|
||||||
* // what follows is only present if there are animations on the widget
|
* // what follows is only present if there are animations on the component
|
||||||
* utils.transitionInsert(vn, "fade");
|
* utils.transitionInsert(vn, "fade");
|
||||||
* },
|
* },
|
||||||
* remove() {
|
* remove() {
|
||||||
@@ -317,7 +317,7 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
|||||||
* },
|
* },
|
||||||
* destroy() {
|
* destroy() {
|
||||||
* // if there are animations, we delay the call to destroy on the
|
* // if there are animations, we delay the call to destroy on the
|
||||||
* // widget, if not, we call it directly.
|
* // component, if not, we call it directly.
|
||||||
* let finalize = () => {
|
* let finalize = () => {
|
||||||
* w4.destroy();
|
* w4.destroy();
|
||||||
* };
|
* };
|
||||||
@@ -328,19 +328,19 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
|||||||
* c1[_2_index] = pvnode;
|
* c1[_2_index] = pvnode;
|
||||||
*
|
*
|
||||||
* // we keep here a reference to the parent vnode (representing the
|
* // we keep here a reference to the parent vnode (representing the
|
||||||
* // widget, so we can reuse it later whenever we update the widget
|
* // component, so we can reuse it later whenever we update the component
|
||||||
* w4.__owl__.pvnode = pvnode;
|
* w4.__owl__.pvnode = pvnode;
|
||||||
* });
|
* });
|
||||||
* } else {
|
* } else {
|
||||||
* // this is the 'update' path of the directive.
|
* // this is the 'update' path of the directive.
|
||||||
* // the call to _updateProps is the actual widget update
|
* // the call to _updateProps is the actual component update
|
||||||
* // Note that we only update the props if we cannot reuse the previous
|
* // Note that we only update the props if we cannot reuse the previous
|
||||||
* // rendering work (in the case it was rendered with the same props)
|
* // rendering work (in the case it was rendered with the same props)
|
||||||
* def3 = def3 || w4._updateProps(props4, extra.forceUpdate, extra.patchQueue);
|
* def3 = def3 || w4._updateProps(props4, extra.forceUpdate, extra.patchQueue);
|
||||||
* def3 = def3.then(() => {
|
* def3 = def3.then(() => {
|
||||||
* // if widget was destroyed in the meantime, we do nothing (so, this
|
* // if component was destroyed in the meantime, we do nothing (so, this
|
||||||
* // means that the parent's element children list will have a null in
|
* // means that the parent's element children list will have a null in
|
||||||
* // the widget's position, which will cause the pvnode to be removed
|
* // the component's position, which will cause the pvnode to be removed
|
||||||
* // when it is patched.
|
* // when it is patched.
|
||||||
* if (w4.__owl__.isDestroyed) {
|
* if (w4.__owl__.isDestroyed) {
|
||||||
* return;
|
* return;
|
||||||
@@ -360,11 +360,11 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
QWeb.addDirective({
|
QWeb.addDirective({
|
||||||
name: "widget",
|
name: "component",
|
||||||
extraNames: ["props", "keepalive", "asyncroot"],
|
extraNames: ["props", "keepalive", "asyncroot"],
|
||||||
priority: 100,
|
priority: 100,
|
||||||
atNodeEncounter({ ctx, value, node, qweb }): boolean {
|
atNodeEncounter({ ctx, value, node, qweb }): boolean {
|
||||||
ctx.addLine("//WIDGET");
|
ctx.addLine("//COMPONENT");
|
||||||
ctx.rootContext.shouldDefineOwner = true;
|
ctx.rootContext.shouldDefineOwner = true;
|
||||||
ctx.rootContext.shouldDefineQWeb = true;
|
ctx.rootContext.shouldDefineQWeb = true;
|
||||||
ctx.rootContext.shouldDefineUtils = true;
|
ctx.rootContext.shouldDefineUtils = true;
|
||||||
@@ -408,7 +408,7 @@ QWeb.addDirective({
|
|||||||
.join(",");
|
.join(",");
|
||||||
let dummyID = ctx.generateID();
|
let dummyID = ctx.generateID();
|
||||||
let defID = ctx.generateID();
|
let defID = ctx.generateID();
|
||||||
let widgetID = ctx.generateID();
|
let componentID = ctx.generateID();
|
||||||
let keyID = key && ctx.generateID();
|
let keyID = key && ctx.generateID();
|
||||||
if (key) {
|
if (key) {
|
||||||
// we bind a variable to the key (could be a complex expression, so we
|
// we bind a variable to the key (could be a complex expression, so we
|
||||||
@@ -419,8 +419,8 @@ QWeb.addDirective({
|
|||||||
let templateID = key
|
let templateID = key
|
||||||
? `key${keyID}`
|
? `key${keyID}`
|
||||||
: ctx.inLoop
|
: ctx.inLoop
|
||||||
? `String(-${widgetID} - i)`
|
? `String(-${componentID} - i)`
|
||||||
: String(widgetID);
|
: String(componentID);
|
||||||
|
|
||||||
let ref = node.getAttribute("t-ref");
|
let ref = node.getAttribute("t-ref");
|
||||||
let refExpr = "";
|
let refExpr = "";
|
||||||
@@ -428,21 +428,21 @@ QWeb.addDirective({
|
|||||||
if (ref) {
|
if (ref) {
|
||||||
refKey = `ref${ctx.generateID()}`;
|
refKey = `ref${ctx.generateID()}`;
|
||||||
ctx.addLine(`const ${refKey} = ${ctx.interpolate(ref)};`);
|
ctx.addLine(`const ${refKey} = ${ctx.interpolate(ref)};`);
|
||||||
refExpr = `context.refs[${refKey}] = w${widgetID};`;
|
refExpr = `context.refs[${refKey}] = w${componentID};`;
|
||||||
}
|
}
|
||||||
let transitionsInsertCode = "";
|
let transitionsInsertCode = "";
|
||||||
if (transition) {
|
if (transition) {
|
||||||
transitionsInsertCode = `utils.transitionInsert(vn, '${transition}');`;
|
transitionsInsertCode = `utils.transitionInsert(vn, '${transition}');`;
|
||||||
}
|
}
|
||||||
let finalizeWidgetCode = `w${widgetID}.${
|
let finalizeComponentCode = `w${componentID}.${
|
||||||
keepAlive ? "unmount" : "destroy"
|
keepAlive ? "unmount" : "destroy"
|
||||||
}();`;
|
}();`;
|
||||||
if (ref && !keepAlive) {
|
if (ref && !keepAlive) {
|
||||||
finalizeWidgetCode += `delete context.refs[${refKey}];`;
|
finalizeComponentCode += `delete context.refs[${refKey}];`;
|
||||||
}
|
}
|
||||||
if (transition) {
|
if (transition) {
|
||||||
finalizeWidgetCode = `let finalize = () => {
|
finalizeComponentCode = `let finalize = () => {
|
||||||
${finalizeWidgetCode}
|
${finalizeComponentCode}
|
||||||
};
|
};
|
||||||
utils.transitionRemove(vn, '${transition}', finalize);`;
|
utils.transitionRemove(vn, '${transition}', finalize);`;
|
||||||
}
|
}
|
||||||
@@ -475,7 +475,7 @@ QWeb.addDirective({
|
|||||||
vn.elm.classList.add(k);
|
vn.elm.classList.add(k);
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
updateClassCode = `let cl=w${widgetID}.el.classList;for (let k in ${attVar}) {if (${attVar}[k]) {cl.add(k)} else {cl.remove(k)}}`;
|
updateClassCode = `let cl=w${componentID}.el.classList;for (let k in ${attVar}) {if (${attVar}[k]) {cl.add(k)} else {cl.remove(k)}}`;
|
||||||
}
|
}
|
||||||
let eventsCode = events
|
let eventsCode = events
|
||||||
.map(function([eventName, mods, handlerName, extraArgs]) {
|
.map(function([eventName, mods, handlerName, extraArgs]) {
|
||||||
@@ -487,7 +487,7 @@ QWeb.addDirective({
|
|||||||
handler = `function (e) {`;
|
handler = `function (e) {`;
|
||||||
handler += mods
|
handler += mods
|
||||||
.map(function(mod) {
|
.map(function(mod) {
|
||||||
return T_WIDGET_MODS_CODE[mod];
|
return T_COMPONENT_MODS_CODE[mod];
|
||||||
})
|
})
|
||||||
.join("");
|
.join("");
|
||||||
handler += `owner['${handlerName}'].call(${params}, e);}`;
|
handler += `owner['${handlerName}'].call(${params}, e);}`;
|
||||||
@@ -503,47 +503,47 @@ QWeb.addDirective({
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`let w${widgetID} = ${templateID} in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[${templateID}]] : false;`
|
`let w${componentID} = ${templateID} in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[${templateID}]] : false;`
|
||||||
);
|
);
|
||||||
ctx.addLine(`let _${dummyID}_index = c${ctx.parentNode}.length;`);
|
ctx.addLine(`let _${dummyID}_index = c${ctx.parentNode}.length;`);
|
||||||
if (async) {
|
if (async) {
|
||||||
ctx.addLine(`const patchQueue${widgetID} = [];`);
|
ctx.addLine(`const patchQueue${componentID} = [];`);
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`c${
|
`c${
|
||||||
ctx.parentNode
|
ctx.parentNode
|
||||||
}.push(w${widgetID} && w${widgetID}.__owl__.pvnode || null);`
|
}.push(w${componentID} && w${componentID}.__owl__.pvnode || null);`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ctx.addLine(`c${ctx.parentNode}.push(null);`);
|
ctx.addLine(`c${ctx.parentNode}.push(null);`);
|
||||||
}
|
}
|
||||||
ctx.addLine(`let props${widgetID} = {${propStr}};`);
|
ctx.addLine(`let props${componentID} = {${propStr}};`);
|
||||||
ctx.addIf(
|
ctx.addIf(
|
||||||
`w${widgetID} && w${widgetID}.__owl__.renderPromise && !w${widgetID}.__owl__.vnode`
|
`w${componentID} && w${componentID}.__owl__.renderPromise && !w${componentID}.__owl__.vnode`
|
||||||
);
|
);
|
||||||
ctx.addIf(
|
ctx.addIf(
|
||||||
`utils.shallowEqual(props${widgetID}, w${widgetID}.__owl__.renderProps)`
|
`utils.shallowEqual(props${componentID}, w${componentID}.__owl__.renderProps)`
|
||||||
);
|
);
|
||||||
ctx.addLine(`def${defID} = w${widgetID}.__owl__.renderPromise;`);
|
ctx.addLine(`def${defID} = w${componentID}.__owl__.renderPromise;`);
|
||||||
ctx.addElse();
|
ctx.addElse();
|
||||||
ctx.addLine(`w${widgetID}.destroy();`);
|
ctx.addLine(`w${componentID}.destroy();`);
|
||||||
ctx.addLine(`w${widgetID} = false;`);
|
ctx.addLine(`w${componentID} = false;`);
|
||||||
ctx.closeIf();
|
ctx.closeIf();
|
||||||
ctx.closeIf();
|
ctx.closeIf();
|
||||||
|
|
||||||
ctx.addIf(`!w${widgetID}`);
|
ctx.addIf(`!w${componentID}`);
|
||||||
// new widget
|
// new component
|
||||||
ctx.addLine(`let widgetKey${widgetID} = ${ctx.interpolate(value)};`);
|
ctx.addLine(`let componentKey${componentID} = ${ctx.interpolate(value)};`);
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`let W${widgetID} = context.widgets && context.widgets[widgetKey${widgetID}] || QWeb.widgets[widgetKey${widgetID}];`
|
`let W${componentID} = context.components && context.components[componentKey${componentID}] || QWeb.components[componentKey${componentID}];`
|
||||||
);
|
);
|
||||||
|
|
||||||
// maybe only do this in dev mode...
|
// maybe only do this in dev mode...
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`if (!W${widgetID}) {throw new Error('Cannot find the definition of widget "' + widgetKey${widgetID} + '"')}`
|
`if (!W${componentID}) {throw new Error('Cannot find the definition of component "' + componentKey${componentID} + '"')}`
|
||||||
);
|
);
|
||||||
ctx.addLine(`w${widgetID} = new W${widgetID}(owner, props${widgetID});`);
|
ctx.addLine(`w${componentID} = new W${componentID}(owner, props${componentID});`);
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`context.__owl__.cmap[${templateID}] = w${widgetID}.__owl__.id;`
|
`context.__owl__.cmap[${templateID}] = w${componentID}.__owl__.id;`
|
||||||
);
|
);
|
||||||
|
|
||||||
// SLOTS
|
// SLOTS
|
||||||
@@ -551,7 +551,7 @@ QWeb.addDirective({
|
|||||||
const clone = <Element>node.cloneNode(true);
|
const clone = <Element>node.cloneNode(true);
|
||||||
const slotNodes = clone.querySelectorAll("[t-set]");
|
const slotNodes = clone.querySelectorAll("[t-set]");
|
||||||
const slotId = qweb.nextSlotId++;
|
const slotId = qweb.nextSlotId++;
|
||||||
ctx.addLine(`w${widgetID}.__owl__.slotId = ${slotId};`);
|
ctx.addLine(`w${componentID}.__owl__.slotId = ${slotId};`);
|
||||||
if (slotNodes.length) {
|
if (slotNodes.length) {
|
||||||
for (let i = 0, length = slotNodes.length; i < length; i++) {
|
for (let i = 0, length = slotNodes.length; i < length; i++) {
|
||||||
const slotNode = slotNodes[i];
|
const slotNode = slotNodes[i];
|
||||||
@@ -569,28 +569,28 @@ QWeb.addDirective({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.addLine(`def${defID} = w${widgetID}._prepare();`);
|
ctx.addLine(`def${defID} = w${componentID}._prepare();`);
|
||||||
// hack: specify empty remove hook to prevent the node from being removed from the DOM
|
// hack: specify empty remove hook to prevent the node from being removed from the DOM
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`def${defID} = def${defID}.then(vnode=>{${createHook}let pvnode=h(vnode.sel, {key: ${templateID}, hook: {insert(vn) {let nvn=w${widgetID}._mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;${refExpr}${transitionsInsertCode}},remove() {},destroy(vn) {${finalizeWidgetCode}}}});c${
|
`def${defID} = def${defID}.then(vnode=>{${createHook}let pvnode=h(vnode.sel, {key: ${templateID}, hook: {insert(vn) {let nvn=w${componentID}._mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;${refExpr}${transitionsInsertCode}},remove() {},destroy(vn) {${finalizeComponentCode}}}});c${
|
||||||
ctx.parentNode
|
ctx.parentNode
|
||||||
}[_${dummyID}_index]=pvnode;w${widgetID}.__owl__.pvnode = pvnode;});`
|
}[_${dummyID}_index]=pvnode;w${componentID}.__owl__.pvnode = pvnode;});`
|
||||||
);
|
);
|
||||||
|
|
||||||
ctx.addElse();
|
ctx.addElse();
|
||||||
// need to update widget
|
// need to update component
|
||||||
const patchQueueCode = async ? `patchQueue${widgetID}` : "extra.patchQueue";
|
const patchQueueCode = async ? `patchQueue${componentID}` : "extra.patchQueue";
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`def${defID} = def${defID} || w${widgetID}._updateProps(props${widgetID}, extra.forceUpdate, ${patchQueueCode});`
|
`def${defID} = def${defID} || w${componentID}._updateProps(props${componentID}, extra.forceUpdate, ${patchQueueCode});`
|
||||||
);
|
);
|
||||||
let keepAliveCode = "";
|
let keepAliveCode = "";
|
||||||
if (keepAlive) {
|
if (keepAlive) {
|
||||||
keepAliveCode = `pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w${widgetID}.el,vn.elm);vn.elm=w${widgetID}.el;w${widgetID}._remount();};`;
|
keepAliveCode = `pvnode.data.hook.insert = vn => {vn.elm.parentNode.replaceChild(w${componentID}.el,vn.elm);vn.elm=w${componentID}.el;w${componentID}._remount();};`;
|
||||||
}
|
}
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`def${defID} = def${defID}.then(()=>{if (w${widgetID}.__owl__.isDestroyed) {return};${
|
`def${defID} = def${defID}.then(()=>{if (w${componentID}.__owl__.isDestroyed) {return};${
|
||||||
tattStyle ? `w${widgetID}.el.style=${tattStyle};` : ""
|
tattStyle ? `w${componentID}.el.style=${tattStyle};` : ""
|
||||||
}${updateClassCode}let pvnode=w${widgetID}.__owl__.pvnode;${keepAliveCode}c${
|
}${updateClassCode}let pvnode=w${componentID}.__owl__.pvnode;${keepAliveCode}c${
|
||||||
ctx.parentNode
|
ctx.parentNode
|
||||||
}[_${dummyID}_index]=pvnode;});`
|
}[_${dummyID}_index]=pvnode;});`
|
||||||
);
|
);
|
||||||
@@ -598,7 +598,7 @@ QWeb.addDirective({
|
|||||||
|
|
||||||
if (async) {
|
if (async) {
|
||||||
ctx.addLine(
|
ctx.addLine(
|
||||||
`def${defID}.then(w${widgetID}._applyPatchQueue.bind(w${widgetID}, patchQueue${widgetID}));`
|
`def${defID}.then(w${componentID}._applyPatchQueue.bind(w${componentID}, patchQueue${componentID}));`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ctx.addLine(`extra.promises.push(def${defID});`);
|
ctx.addLine(`extra.promises.push(def${defID});`);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ exports[`animations t-transition combined with component 1`] = `
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -24,9 +24,9 @@ exports[`animations t-transition combined with component 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`Child\`;
|
let componentKey4 = \`Child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -43,7 +43,7 @@ exports[`animations t-transition combined with component 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`animations t-transition combined with t-widget and t-if 1`] = `
|
exports[`animations t-transition combined with t-component and t-if 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -53,7 +53,7 @@ exports[`animations t-transition combined with t-widget and t-if 1`] = `
|
|||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
if (context['state'].display) {
|
if (context['state'].display) {
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -68,9 +68,9 @@ exports[`animations t-transition combined with t-widget and t-if 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`Child\`;
|
let componentKey4 = \`Child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = `
|
|||||||
let c4 = [], p4 = {key:4,attrs:{class: _3}};
|
let c4 = [], p4 = {key:4,attrs:{class: _3}};
|
||||||
var vn4 = h('div', p4, c4);
|
var vn4 = h('div', p4, c4);
|
||||||
c1.push(vn4);
|
c1.push(vn4);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def6;
|
let def6;
|
||||||
let w7 = 7 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[7]] : false;
|
let w7 = 7 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[7]] : false;
|
||||||
let _5_index = c4.length;
|
let _5_index = c4.length;
|
||||||
@@ -37,9 +37,9 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w7) {
|
if (!w7) {
|
||||||
let widgetKey7 = \`Child\`;
|
let componentKey7 = \`Child\`;
|
||||||
let W7 = context.widgets && context.widgets[widgetKey7] || QWeb.widgets[widgetKey7];
|
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
|
||||||
if (!W7) {throw new Error('Cannot find the definition of widget \\"' + widgetKey7 + '\\"')}
|
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
|
||||||
w7 = new W7(owner, props7);
|
w7 = new W7(owner, props7);
|
||||||
context.__owl__.cmap[7] = w7.__owl__.id;
|
context.__owl__.cmap[7] = w7.__owl__.id;
|
||||||
def6 = w7._prepare();
|
def6 = w7._prepare();
|
||||||
@@ -49,7 +49,7 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = `
|
|||||||
def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c4[_5_index]=pvnode;});
|
def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c4[_5_index]=pvnode;});
|
||||||
}
|
}
|
||||||
extra.promises.push(def6);
|
extra.promises.push(def6);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def9;
|
let def9;
|
||||||
let w10 = 10 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[10]] : false;
|
let w10 = 10 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[10]] : false;
|
||||||
let _8_index = c4.length;
|
let _8_index = c4.length;
|
||||||
@@ -65,9 +65,9 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w10) {
|
if (!w10) {
|
||||||
let widgetKey10 = \`AsyncChild\`;
|
let componentKey10 = \`AsyncChild\`;
|
||||||
let W10 = context.widgets && context.widgets[widgetKey10] || QWeb.widgets[widgetKey10];
|
let W10 = context.components && context.components[componentKey10] || QWeb.components[componentKey10];
|
||||||
if (!W10) {throw new Error('Cannot find the definition of widget \\"' + widgetKey10 + '\\"')}
|
if (!W10) {throw new Error('Cannot find the definition of component \\"' + componentKey10 + '\\"')}
|
||||||
w10 = new W10(owner, props10);
|
w10 = new W10(owner, props10);
|
||||||
context.__owl__.cmap[10] = w10.__owl__.id;
|
context.__owl__.cmap[10] = w10.__owl__.id;
|
||||||
def9 = w10._prepare();
|
def9 = w10._prepare();
|
||||||
@@ -103,7 +103,7 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = `
|
|||||||
let c4 = [], p4 = {key:4,attrs:{class: _3}};
|
let c4 = [], p4 = {key:4,attrs:{class: _3}};
|
||||||
var vn4 = h('div', p4, c4);
|
var vn4 = h('div', p4, c4);
|
||||||
c1.push(vn4);
|
c1.push(vn4);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def6;
|
let def6;
|
||||||
let w7 = 7 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[7]] : false;
|
let w7 = 7 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[7]] : false;
|
||||||
let _5_index = c4.length;
|
let _5_index = c4.length;
|
||||||
@@ -119,9 +119,9 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w7) {
|
if (!w7) {
|
||||||
let widgetKey7 = \`Child\`;
|
let componentKey7 = \`Child\`;
|
||||||
let W7 = context.widgets && context.widgets[widgetKey7] || QWeb.widgets[widgetKey7];
|
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
|
||||||
if (!W7) {throw new Error('Cannot find the definition of widget \\"' + widgetKey7 + '\\"')}
|
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
|
||||||
w7 = new W7(owner, props7);
|
w7 = new W7(owner, props7);
|
||||||
context.__owl__.cmap[7] = w7.__owl__.id;
|
context.__owl__.cmap[7] = w7.__owl__.id;
|
||||||
def6 = w7._prepare();
|
def6 = w7._prepare();
|
||||||
@@ -131,7 +131,7 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = `
|
|||||||
def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c4[_5_index]=pvnode;});
|
def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c4[_5_index]=pvnode;});
|
||||||
}
|
}
|
||||||
def6.then(w7._applyPatchQueue.bind(w7, patchQueue7));
|
def6.then(w7._applyPatchQueue.bind(w7, patchQueue7));
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def9;
|
let def9;
|
||||||
let w10 = 10 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[10]] : false;
|
let w10 = 10 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[10]] : false;
|
||||||
let _8_index = c4.length;
|
let _8_index = c4.length;
|
||||||
@@ -146,9 +146,9 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w10) {
|
if (!w10) {
|
||||||
let widgetKey10 = \`AsyncChild\`;
|
let componentKey10 = \`AsyncChild\`;
|
||||||
let W10 = context.widgets && context.widgets[widgetKey10] || QWeb.widgets[widgetKey10];
|
let W10 = context.components && context.components[componentKey10] || QWeb.components[componentKey10];
|
||||||
if (!W10) {throw new Error('Cannot find the definition of widget \\"' + widgetKey10 + '\\"')}
|
if (!W10) {throw new Error('Cannot find the definition of component \\"' + componentKey10 + '\\"')}
|
||||||
w10 = new W10(owner, props10);
|
w10 = new W10(owner, props10);
|
||||||
context.__owl__.cmap[10] = w10.__owl__.id;
|
context.__owl__.cmap[10] = w10.__owl__.id;
|
||||||
def9 = w10._prepare();
|
def9 = w10._prepare();
|
||||||
@@ -162,7 +162,7 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`async rendering t-widget with t-asyncroot directive: mixed re-renderings 1`] = `
|
exports[`async rendering t-component with t-asyncroot directive: mixed re-renderings 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -184,7 +184,7 @@ exports[`async rendering t-widget with t-asyncroot directive: mixed re-rendering
|
|||||||
let c4 = [], p4 = {key:4,attrs:{class: _3}};
|
let c4 = [], p4 = {key:4,attrs:{class: _3}};
|
||||||
var vn4 = h('div', p4, c4);
|
var vn4 = h('div', p4, c4);
|
||||||
c1.push(vn4);
|
c1.push(vn4);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def6;
|
let def6;
|
||||||
let w7 = 7 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[7]] : false;
|
let w7 = 7 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[7]] : false;
|
||||||
let _5_index = c4.length;
|
let _5_index = c4.length;
|
||||||
@@ -199,9 +199,9 @@ exports[`async rendering t-widget with t-asyncroot directive: mixed re-rendering
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w7) {
|
if (!w7) {
|
||||||
let widgetKey7 = \`Child\`;
|
let componentKey7 = \`Child\`;
|
||||||
let W7 = context.widgets && context.widgets[widgetKey7] || QWeb.widgets[widgetKey7];
|
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
|
||||||
if (!W7) {throw new Error('Cannot find the definition of widget \\"' + widgetKey7 + '\\"')}
|
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
|
||||||
w7 = new W7(owner, props7);
|
w7 = new W7(owner, props7);
|
||||||
context.__owl__.cmap[7] = w7.__owl__.id;
|
context.__owl__.cmap[7] = w7.__owl__.id;
|
||||||
def6 = w7._prepare();
|
def6 = w7._prepare();
|
||||||
@@ -211,7 +211,7 @@ exports[`async rendering t-widget with t-asyncroot directive: mixed re-rendering
|
|||||||
def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c4[_5_index]=pvnode;});
|
def6 = def6.then(()=>{if (w7.__owl__.isDestroyed) {return};let pvnode=w7.__owl__.pvnode;c4[_5_index]=pvnode;});
|
||||||
}
|
}
|
||||||
extra.promises.push(def6);
|
extra.promises.push(def6);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def9;
|
let def9;
|
||||||
let w10 = 10 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[10]] : false;
|
let w10 = 10 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[10]] : false;
|
||||||
let _8_index = c4.length;
|
let _8_index = c4.length;
|
||||||
@@ -227,9 +227,9 @@ exports[`async rendering t-widget with t-asyncroot directive: mixed re-rendering
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w10) {
|
if (!w10) {
|
||||||
let widgetKey10 = \`AsyncChild\`;
|
let componentKey10 = \`AsyncChild\`;
|
||||||
let W10 = context.widgets && context.widgets[widgetKey10] || QWeb.widgets[widgetKey10];
|
let W10 = context.components && context.components[componentKey10] || QWeb.components[componentKey10];
|
||||||
if (!W10) {throw new Error('Cannot find the definition of widget \\"' + widgetKey10 + '\\"')}
|
if (!W10) {throw new Error('Cannot find the definition of component \\"' + componentKey10 + '\\"')}
|
||||||
w10 = new W10(owner, props10);
|
w10 = new W10(owner, props10);
|
||||||
context.__owl__.cmap[10] = w10.__owl__.id;
|
context.__owl__.cmap[10] = w10.__owl__.id;
|
||||||
def9 = w10._prepare();
|
def9 = w10._prepare();
|
||||||
@@ -243,7 +243,7 @@ exports[`async rendering t-widget with t-asyncroot directive: mixed re-rendering
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`class and style attributes with t-widget dynamic t-att-style is properly added and updated on widget root el 1`] = `
|
exports[`class and style attributes with t-component dynamic t-att-style is properly added and updated on widget root el 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -252,7 +252,7 @@ exports[`class and style attributes with t-widget dynamic t-att-style is properl
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
const _5 = context['state'].style;
|
const _5 = context['state'].style;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
@@ -268,9 +268,9 @@ exports[`class and style attributes with t-widget dynamic t-att-style is properl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -284,7 +284,7 @@ exports[`class and style attributes with t-widget dynamic t-att-style is properl
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`class and style attributes with t-widget t-att-class is properly added/removed on widget root el 1`] = `
|
exports[`class and style attributes with t-component t-att-class is properly added/removed on widget root el 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -293,7 +293,7 @@ exports[`class and style attributes with t-widget t-att-class is properly added/
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
const _5 = {a:context['state'].a,b:context['state'].b};
|
const _5 = {a:context['state'].a,b:context['state'].b};
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
@@ -309,9 +309,9 @@ exports[`class and style attributes with t-widget t-att-class is properly added/
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -329,7 +329,7 @@ exports[`class and style attributes with t-widget t-att-class is properly added/
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`composition sub widgets with some state rendered in a loop 1`] = `
|
exports[`composition sub components with some state rendered in a loop 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -353,7 +353,7 @@ exports[`composition sub widgets with some state rendered in a loop 1`] = `
|
|||||||
context.number_index = i;
|
context.number_index = i;
|
||||||
context.number = _3[i];
|
context.number = _3[i];
|
||||||
context.number_value = _4[i];
|
context.number_value = _4[i];
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let key8 = context['number'];
|
let key8 = context['number'];
|
||||||
let def6;
|
let def6;
|
||||||
let w7 = key8 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[key8]] : false;
|
let w7 = key8 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[key8]] : false;
|
||||||
@@ -369,9 +369,9 @@ exports[`composition sub widgets with some state rendered in a loop 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w7) {
|
if (!w7) {
|
||||||
let widgetKey7 = \`ChildWidget\`;
|
let componentKey7 = \`ChildWidget\`;
|
||||||
let W7 = context.widgets && context.widgets[widgetKey7] || QWeb.widgets[widgetKey7];
|
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
|
||||||
if (!W7) {throw new Error('Cannot find the definition of widget \\"' + widgetKey7 + '\\"')}
|
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
|
||||||
w7 = new W7(owner, props7);
|
w7 = new W7(owner, props7);
|
||||||
context.__owl__.cmap[key8] = w7.__owl__.id;
|
context.__owl__.cmap[key8] = w7.__owl__.id;
|
||||||
def6 = w7._prepare();
|
def6 = w7._prepare();
|
||||||
@@ -386,7 +386,7 @@ exports[`composition sub widgets with some state rendered in a loop 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`composition t-widget with dynamic value 1`] = `
|
exports[`composition t-component with dynamic value 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -395,7 +395,7 @@ exports[`composition t-widget with dynamic value 1`] = `
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -410,9 +410,9 @@ exports[`composition t-widget with dynamic value 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = (context['state'].widget);
|
let componentKey4 = (context['state'].widget);
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -426,7 +426,7 @@ exports[`composition t-widget with dynamic value 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`composition t-widget with dynamic value 2 1`] = `
|
exports[`composition t-component with dynamic value 2 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -435,7 +435,7 @@ exports[`composition t-widget with dynamic value 2 1`] = `
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -450,9 +450,9 @@ exports[`composition t-widget with dynamic value 2 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`Widget\${context['state'].widget}\`;
|
let componentKey4 = \`Widget\${context['state'].widget}\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -466,7 +466,7 @@ exports[`composition t-widget with dynamic value 2 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`other directives with t-widget t-on with handler bound to argument 1`] = `
|
exports[`other directives with t-component t-on with handler bound to argument 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -475,7 +475,7 @@ exports[`other directives with t-widget t-on with handler bound to argument 1`]
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -490,9 +490,9 @@ exports[`other directives with t-widget t-on with handler bound to argument 1`]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -506,7 +506,7 @@ exports[`other directives with t-widget t-on with handler bound to argument 1`]
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`other directives with t-widget t-on with handler bound to empty object (with non empty inner string) 1`] = `
|
exports[`other directives with t-component t-on with handler bound to empty object (with non empty inner string) 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -515,7 +515,7 @@ exports[`other directives with t-widget t-on with handler bound to empty object
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -530,9 +530,9 @@ exports[`other directives with t-widget t-on with handler bound to empty object
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -546,7 +546,7 @@ exports[`other directives with t-widget t-on with handler bound to empty object
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`other directives with t-widget t-on with handler bound to empty object 1`] = `
|
exports[`other directives with t-component t-on with handler bound to empty object 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -555,7 +555,7 @@ exports[`other directives with t-widget t-on with handler bound to empty object
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -570,9 +570,9 @@ exports[`other directives with t-widget t-on with handler bound to empty object
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -586,7 +586,7 @@ exports[`other directives with t-widget t-on with handler bound to empty object
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`other directives with t-widget t-on with handler bound to object 1`] = `
|
exports[`other directives with t-component t-on with handler bound to object 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -595,7 +595,7 @@ exports[`other directives with t-widget t-on with handler bound to object 1`] =
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -610,9 +610,9 @@ exports[`other directives with t-widget t-on with handler bound to object 1`] =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -626,7 +626,7 @@ exports[`other directives with t-widget t-on with handler bound to object 1`] =
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`other directives with t-widget t-on with prevent and self modifiers (order matters) 1`] = `
|
exports[`other directives with t-component t-on with prevent and self modifiers (order matters) 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -635,7 +635,7 @@ exports[`other directives with t-widget t-on with prevent and self modifiers (or
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -650,9 +650,9 @@ exports[`other directives with t-widget t-on with prevent and self modifiers (or
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`Child\`;
|
let componentKey4 = \`Child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -666,7 +666,7 @@ exports[`other directives with t-widget t-on with prevent and self modifiers (or
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`other directives with t-widget t-on with self and prevent modifiers (order matters) 1`] = `
|
exports[`other directives with t-component t-on with self and prevent modifiers (order matters) 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -675,7 +675,7 @@ exports[`other directives with t-widget t-on with self and prevent modifiers (or
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -690,9 +690,9 @@ exports[`other directives with t-widget t-on with self and prevent modifiers (or
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -706,7 +706,7 @@ exports[`other directives with t-widget t-on with self and prevent modifiers (or
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`other directives with t-widget t-on with self modifier 1`] = `
|
exports[`other directives with t-component t-on with self modifier 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -715,7 +715,7 @@ exports[`other directives with t-widget t-on with self modifier 1`] = `
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -730,9 +730,9 @@ exports[`other directives with t-widget t-on with self modifier 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -746,7 +746,7 @@ exports[`other directives with t-widget t-on with self modifier 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`other directives with t-widget t-on with stop and/or prevent modifiers 1`] = `
|
exports[`other directives with t-component t-on with stop and/or prevent modifiers 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
let utils = this.utils;
|
let utils = this.utils;
|
||||||
@@ -755,7 +755,7 @@ exports[`other directives with t-widget t-on with stop and/or prevent modifiers
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -770,9 +770,9 @@ exports[`other directives with t-widget t-on with stop and/or prevent modifiers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -795,7 +795,7 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = `
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let key5 = 'somestring';
|
let key5 = 'somestring';
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = key5 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[key5]] : false;
|
let w4 = key5 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[key5]] : false;
|
||||||
@@ -811,9 +811,9 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`child\`;
|
let componentKey4 = \`child\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[key5] = w4.__owl__.id;
|
context.__owl__.cmap[key5] = w4.__owl__.id;
|
||||||
def3 = w4._prepare();
|
def3 = w4._prepare();
|
||||||
@@ -983,7 +983,7 @@ exports[`t-slot directive can define and call slots 1`] = `
|
|||||||
var h = this.utils.h;
|
var h = this.utils.h;
|
||||||
let c1 = [], p1 = {key:1};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('div', p1, c1);
|
var vn1 = h('div', p1, c1);
|
||||||
//WIDGET
|
//COMPONENT
|
||||||
let def3;
|
let def3;
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
||||||
let _2_index = c1.length;
|
let _2_index = c1.length;
|
||||||
@@ -998,9 +998,9 @@ exports[`t-slot directive can define and call slots 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!w4) {
|
if (!w4) {
|
||||||
let widgetKey4 = \`Dialog\`;
|
let componentKey4 = \`Dialog\`;
|
||||||
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
|
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
|
||||||
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
|
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||||
w4 = new W4(owner, props4);
|
w4 = new W4(owner, props4);
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
context.__owl__.cmap[4] = w4.__owl__.id;
|
||||||
w4.__owl__.slotId = 1;
|
w4.__owl__.slotId = 1;
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
function anonymous(context, extra) {
|
|
||||||
var h = this.utils.h;
|
|
||||||
let c1 = [], p1 = {key:1};
|
|
||||||
var vn1 = h('div', p1, c1);
|
|
||||||
if (context['state'].display) {
|
|
||||||
//WIDGET
|
|
||||||
let _2_index = c1.length;
|
|
||||||
c1.push(null);
|
|
||||||
let def3;
|
|
||||||
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
|
|
||||||
let props4 = {};
|
|
||||||
if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode && props4 !== w4.__owl__.renderProps) {
|
|
||||||
w4.destroy();
|
|
||||||
w4 = false
|
|
||||||
}
|
|
||||||
if (!w4) {
|
|
||||||
let W4 = context.widgets['Child'];
|
|
||||||
if (!W4) {throw new Error(`Cannot find the definition of widget "Child"`)}
|
|
||||||
w4 = new W4(owner, props4);
|
|
||||||
context.__owl__.cmap[4] = w4.__owl__.id;
|
|
||||||
def3 = w4._prepare();
|
|
||||||
def3 = def3.then(vnode=>{let pvnode=h(vnode.sel, {key: 4, hook: {insert: (vn) => {let nvn=w4._mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;this.utils.transitionInsert(vn.elm, 'chimay');},remove: () => {},destroy: (vn) => {let finalize = () => {
|
|
||||||
w4.destroy();
|
|
||||||
};
|
|
||||||
this.utils.transitionRemove(vn.elm, 'chimay', finalize);}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
|
|
||||||
} else {
|
|
||||||
def3 = w4._updateProps(props4, extra.forceUpdate, extra.patchQueue);
|
|
||||||
def3 = def3.then(()=>{if (w4.__owl__.isDestroyed) {return};let pvnode=w4.__owl__.pvnode;c1[_2_index]=pvnode;});
|
|
||||||
}
|
|
||||||
extra.promises.push(def3);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
// - fixture: a div, appended to the DOM, intended to be the target of dom
|
// - fixture: a div, appended to the DOM, intended to be the target of dom
|
||||||
// manipulations. Note that it is removed after each test.
|
// manipulations. Note that it is removed after each test.
|
||||||
// - qweb: a new QWeb instance
|
// - qweb: a new QWeb instance
|
||||||
// - env: a WEnv, necessary to create new widgets
|
// - env: a WEnv, necessary to create new components
|
||||||
// - cssEl: a stylesheet injected into the dom
|
// - cssEl: a stylesheet injected into the dom
|
||||||
|
|
||||||
let fixture: HTMLElement;
|
let fixture: HTMLElement;
|
||||||
@@ -179,7 +179,7 @@ describe("animations", () => {
|
|||||||
);
|
);
|
||||||
env.qweb.addTemplate("Child", `<span>blue</span>`);
|
env.qweb.addTemplate("Child", `<span>blue</span>`);
|
||||||
class Parent extends Widget {
|
class Parent extends Widget {
|
||||||
widgets = { Child: Child };
|
components = { Child: Child };
|
||||||
}
|
}
|
||||||
class Child extends Widget {}
|
class Child extends Widget {}
|
||||||
const widget = new Parent(env);
|
const widget = new Parent(env);
|
||||||
@@ -209,16 +209,16 @@ describe("animations", () => {
|
|||||||
expect(fixture.innerHTML).toBe('<div><span class="">blue</span></div>');
|
expect(fixture.innerHTML).toBe('<div><span class="">blue</span></div>');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("t-transition combined with t-widget and t-if", async () => {
|
test("t-transition combined with t-component and t-if", async () => {
|
||||||
expect.assertions(8);
|
expect.assertions(8);
|
||||||
|
|
||||||
env.qweb.addTemplate(
|
env.qweb.addTemplate(
|
||||||
"Parent",
|
"Parent",
|
||||||
`<div><t t-if="state.display" t-widget="Child" t-transition="chimay"/></div>`
|
`<div><t t-if="state.display" t-component="Child" t-transition="chimay"/></div>`
|
||||||
);
|
);
|
||||||
env.qweb.addTemplate("Child", `<span>blue</span>`);
|
env.qweb.addTemplate("Child", `<span>blue</span>`);
|
||||||
class Parent extends Widget {
|
class Parent extends Widget {
|
||||||
widgets = { Child: Child };
|
components = { Child: Child };
|
||||||
state = { display: true };
|
state = { display: true };
|
||||||
}
|
}
|
||||||
class Child extends Widget {}
|
class Child extends Widget {}
|
||||||
@@ -351,21 +351,21 @@ describe("animations", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("t-transition combined with t-widget, remove and re-add before transitionend", async () => {
|
test("t-transition combined with t-component, remove and re-add before transitionend", async () => {
|
||||||
expect.assertions(11);
|
expect.assertions(11);
|
||||||
|
|
||||||
env.qweb.addTemplates(
|
env.qweb.addTemplates(
|
||||||
`<templates>
|
`<templates>
|
||||||
<div t-name="Parent">
|
<div t-name="Parent">
|
||||||
<button t-on-click="toggle">Toggle</button>
|
<button t-on-click="toggle">Toggle</button>
|
||||||
<t t-if="state.flag" t-widget="Child" t-transition="chimay"/>
|
<t t-if="state.flag" t-component="Child" t-transition="chimay"/>
|
||||||
</div>
|
</div>
|
||||||
<span t-name="Child">blue</span>
|
<span t-name="Child">blue</span>
|
||||||
</templates>`
|
</templates>`
|
||||||
);
|
);
|
||||||
class Child extends Widget {}
|
class Child extends Widget {}
|
||||||
class Parent extends Widget {
|
class Parent extends Widget {
|
||||||
widgets = { Child };
|
components = { Child };
|
||||||
constructor(parent) {
|
constructor(parent) {
|
||||||
super(parent);
|
super(parent);
|
||||||
this.state = { flag: false };
|
this.state = { flag: false };
|
||||||
|
|||||||
+171
-171
File diff suppressed because it is too large
Load Diff
@@ -54,7 +54,7 @@ describe("props validation", () => {
|
|||||||
try {
|
try {
|
||||||
await w._updateProps({});
|
await w._updateProps({});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
expect(e.message).toBe("Missing props 'message' (widget 'TestWidget')");
|
expect(e.message).toBe("Missing props 'message' (component 'TestWidget')");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ describe("props validation", () => {
|
|||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
new TestWidget(env);
|
new TestWidget(env);
|
||||||
}).toThrow("Missing props 'message' (widget 'TestWidget')");
|
}).toThrow("Missing props 'message' (component 'TestWidget')");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("validate simple types", async () => {
|
test("validate simple types", async () => {
|
||||||
@@ -93,7 +93,7 @@ describe("props validation", () => {
|
|||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
new TestWidget(env, { p: test.ko });
|
new TestWidget(env, { p: test.ko });
|
||||||
}).toThrow("Props 'p' of invalid type in widget");
|
}).toThrow("Props 'p' of invalid type in component");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ describe("props validation", () => {
|
|||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
new TestWidget(env, { p: test.ko });
|
new TestWidget(env, { p: test.ko });
|
||||||
}).toThrow("Props 'p' of invalid type in widget");
|
}).toThrow("Props 'p' of invalid type in component");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ describe("props validation", () => {
|
|||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
new TestWidget(env, { p: 1 });
|
new TestWidget(env, { p: 1 });
|
||||||
}).toThrow("Props 'p' of invalid type in widget");
|
}).toThrow("Props 'p' of invalid type in component");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can validate an optional props", async () => {
|
test("can validate an optional props", async () => {
|
||||||
|
|||||||
+10
-10
@@ -541,7 +541,7 @@ describe("connecting a component to store", () => {
|
|||||||
);
|
);
|
||||||
env.qweb.addTemplate("Todo", `<span><t t-esc="props.msg"/></span>`);
|
env.qweb.addTemplate("Todo", `<span><t t-esc="props.msg"/></span>`);
|
||||||
class App extends Component<any, any, any> {
|
class App extends Component<any, any, any> {
|
||||||
widgets = { Todo };
|
components = { Todo };
|
||||||
}
|
}
|
||||||
class Todo extends Component<any, any, any> {}
|
class Todo extends Component<any, any, any> {}
|
||||||
const state = { todos: [] };
|
const state = { todos: [] };
|
||||||
@@ -632,7 +632,7 @@ describe("connecting a component to store", () => {
|
|||||||
</templates>
|
</templates>
|
||||||
`);
|
`);
|
||||||
class App extends Component<any, any, any> {
|
class App extends Component<any, any, any> {
|
||||||
widgets = { Todo };
|
components = { Todo };
|
||||||
}
|
}
|
||||||
class Todo extends Component<any, any, any> {}
|
class Todo extends Component<any, any, any> {}
|
||||||
|
|
||||||
@@ -686,11 +686,11 @@ describe("connecting a component to store", () => {
|
|||||||
"Parent",
|
"Parent",
|
||||||
`
|
`
|
||||||
<div>
|
<div>
|
||||||
<t t-if="state.child" t-widget="ConnectedChild"/>
|
<t t-if="state.child" t-component="ConnectedChild"/>
|
||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
class Parent extends Component<any, any, any> {
|
class Parent extends Component<any, any, any> {
|
||||||
widgets = { ConnectedChild };
|
components = { ConnectedChild };
|
||||||
|
|
||||||
constructor(env: Env) {
|
constructor(env: Env) {
|
||||||
super(env);
|
super(env);
|
||||||
@@ -739,7 +739,7 @@ describe("connecting a component to store", () => {
|
|||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
class TodoList extends Component<any, any, any> {
|
class TodoList extends Component<any, any, any> {
|
||||||
widgets = { ConnectedTodo };
|
components = { ConnectedTodo };
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStoreToProps(state) {
|
function mapStoreToProps(state) {
|
||||||
@@ -806,7 +806,7 @@ describe("connecting a component to store", () => {
|
|||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
class TodoList extends Component<any, any, any> {
|
class TodoList extends Component<any, any, any> {
|
||||||
widgets = { ConnectedTodo };
|
components = { ConnectedTodo };
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStoreToProps(state) {
|
function mapStoreToProps(state) {
|
||||||
@@ -843,7 +843,7 @@ describe("connecting a component to store", () => {
|
|||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
class App extends Component<any, any, any> {
|
class App extends Component<any, any, any> {
|
||||||
widgets = { ConnectedBeer };
|
components = { ConnectedBeer };
|
||||||
state = { beerId: 1 };
|
state = { beerId: 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -927,7 +927,7 @@ describe("connecting a component to store", () => {
|
|||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
class App extends Component<any, any, any> {
|
class App extends Component<any, any, any> {
|
||||||
widgets = { ConnectedBeer };
|
components = { ConnectedBeer };
|
||||||
state = { beerId: 0 };
|
state = { beerId: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,7 +999,7 @@ describe("connecting a component to store", () => {
|
|||||||
</div>`
|
</div>`
|
||||||
);
|
);
|
||||||
class App extends Component<any, any, any> {
|
class App extends Component<any, any, any> {
|
||||||
widgets = { ConnectedBeer };
|
components = { ConnectedBeer };
|
||||||
state = { beerId: 0 };
|
state = { beerId: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1079,7 +1079,7 @@ describe("connecting a component to store", () => {
|
|||||||
`
|
`
|
||||||
);
|
);
|
||||||
class Parent extends Component<any, any, any> {
|
class Parent extends Component<any, any, any> {
|
||||||
widgets = { Child: ConnectedChild };
|
components = { Child: ConnectedChild };
|
||||||
}
|
}
|
||||||
const ConnectedParent = connect(
|
const ConnectedParent = connect(
|
||||||
Parent,
|
Parent,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class Counter extends owl.Component {
|
|||||||
// Message Widget
|
// Message Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class Message extends owl.Component {
|
class Message extends owl.Component {
|
||||||
widgets = { Counter };
|
components = { Counter };
|
||||||
|
|
||||||
shouldUpdate(nextProps) {
|
shouldUpdate(nextProps) {
|
||||||
return nextProps.message !== this.props.message;
|
return nextProps.message !== this.props.message;
|
||||||
@@ -36,7 +36,7 @@ class Message extends owl.Component {
|
|||||||
// Root Widget
|
// Root Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
widgets = { Message };
|
components = { Message };
|
||||||
state = { messages: [], multipleFlag: false, clearAfterFlag: false };
|
state = { messages: [], multipleFlag: false, clearAfterFlag: false };
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<div class="right-thing">
|
<div class="right-thing">
|
||||||
<div class="content" t-on-remove-message="removeMessage">
|
<div class="content" t-on-remove-message="removeMessage">
|
||||||
<t t-foreach="state.messages" t-as="message">
|
<t t-foreach="state.messages" t-as="message">
|
||||||
<t t-widget="Message" t-key="message.id" message="message"/>
|
<Message t-key="message.id" message="message"/>
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
<span class="author"><t t-esc="props.message.author"/></span>
|
<span class="author"><t t-esc="props.message.author"/></span>
|
||||||
<span class="msg"><t t-esc="props.message.msg"/></span>
|
<span class="msg"><t t-esc="props.message.msg"/></span>
|
||||||
<button class="remove" t-on-click="removeMessage">Remove</button>
|
<button class="remove" t-on-click="removeMessage">Remove</button>
|
||||||
<t t-widget="Counter"/>
|
<Counter/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="Counter">
|
<div t-name="Counter">
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ class App extends owl.Component {
|
|||||||
super(...args);
|
super(...args);
|
||||||
this.version = owl.__info__.version;
|
this.version = owl.__info__.version;
|
||||||
this.SAMPLES = SAMPLES;
|
this.SAMPLES = SAMPLES;
|
||||||
this.widgets = { TabbedEditor };
|
this.components = { TabbedEditor };
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
js: SAMPLES[0].code,
|
js: SAMPLES[0].code,
|
||||||
|
|||||||
+36
-36
@@ -8,9 +8,9 @@ class Counter extends owl.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main root widget
|
// Main root component
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
widgets = { Counter };
|
components = { Counter };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Application setup
|
// Application setup
|
||||||
@@ -49,8 +49,8 @@ class Counter extends owl.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
state = { flag: false, widgetFlag: false, numbers: [] };
|
state = { flag: false, componentFlag: false, numbers: [] };
|
||||||
widgets = { Counter };
|
components = { Counter };
|
||||||
|
|
||||||
toggle(key) {
|
toggle(key) {
|
||||||
this.state[key] = !this.state[key];
|
this.state[key] = !this.state[key];
|
||||||
@@ -83,12 +83,12 @@ const ANIMATION_XML = `<templates>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>Transition on sub widgets</h2>
|
<h2>Transition on sub components</h2>
|
||||||
|
|
||||||
<div class="demo">
|
<div class="demo">
|
||||||
<button t-on-click="toggle('widgetFlag')">Toggle widget</button>
|
<button t-on-click="toggle('componentFlag')">Toggle component</button>
|
||||||
<div>
|
<div>
|
||||||
<Counter t-if="state.widgetFlag" t-transition="fade"/>
|
<Counter t-if="state.componentFlag" t-transition="fade"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -173,12 +173,12 @@ const ANIMATION_CSS = `button {
|
|||||||
|
|
||||||
const LIFECYCLE_DEMO = `// This example shows all the possible lifecycle hooks
|
const LIFECYCLE_DEMO = `// This example shows all the possible lifecycle hooks
|
||||||
//
|
//
|
||||||
// The root widget controls a sub widget (DemoWidget). It logs all its lifecycle
|
// The root component controls a sub component (DemoComponent). It logs all its lifecycle
|
||||||
// methods in the console. Try modifying its state by clicking on it, or by
|
// methods in the console. Try modifying its state by clicking on it, or by
|
||||||
// clicking on the two main buttons, and look into the console to see what
|
// clicking on the two main buttons, and look into the console to see what
|
||||||
// happens.
|
// happens.
|
||||||
|
|
||||||
class DemoWidget extends owl.Component {
|
class DemoComponent extends owl.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(...arguments);
|
super(...arguments);
|
||||||
this.state = { n: 0 };
|
this.state = { n: 0 };
|
||||||
@@ -208,14 +208,14 @@ class DemoWidget extends owl.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
widgets = { DemoWidget };
|
components = { DemoComponent };
|
||||||
state = { n: 0, flag: true };
|
state = { n: 0, flag: true };
|
||||||
|
|
||||||
increment() {
|
increment() {
|
||||||
this.state.n++;
|
this.state.n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSubWidget() {
|
toggleSubComponent() {
|
||||||
this.state.flag = !this.state.flag;
|
this.state.flag = !this.state.flag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,17 +226,17 @@ app.mount(document.body);
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const LIFECYCLE_DEMO_XML = `<templates>
|
const LIFECYCLE_DEMO_XML = `<templates>
|
||||||
<div t-name="DemoWidget" t-on-click="increment" class="demo">
|
<div t-name="DemoComponent" t-on-click="increment" class="demo">
|
||||||
<div>Demo Sub Widget</div>
|
<div>Demo Sub Component</div>
|
||||||
<div>(click on me to update me)</div>
|
<div>(click on me to update me)</div>
|
||||||
<div>Props: <t t-esc="props.n"/>, State: <t t-esc="state.n"/>. </div>
|
<div>Props: <t t-esc="props.n"/>, State: <t t-esc="state.n"/>. </div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="App">
|
<div t-name="App">
|
||||||
<button t-on-click="increment">Increment Parent State</button>
|
<button t-on-click="increment">Increment Parent State</button>
|
||||||
<button t-on-click="toggleSubWidget">Toggle SubWidget</button>
|
<button t-on-click="toggleSubComponent">Toggle SubComponent</button>
|
||||||
<div t-if="state.flag">
|
<div t-if="state.flag">
|
||||||
<DemoWidget n="state.n"/>
|
<DemoComponent n="state.n"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</templates>`;
|
</templates>`;
|
||||||
@@ -406,7 +406,7 @@ function mapStoreToProps(state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TodoApp extends owl.Component {
|
class TodoApp extends owl.Component {
|
||||||
widgets = { TodoItem };
|
components = { TodoItem };
|
||||||
state = { filter: "all" };
|
state = { filter: "all" };
|
||||||
|
|
||||||
get visibleTodos() {
|
get visibleTodos() {
|
||||||
@@ -910,7 +910,7 @@ const RESPONSIVE = `// In this example, we show how we can modify keys in the gl
|
|||||||
//
|
//
|
||||||
// The main idea is to have a "isMobile" key in the environment, then listen
|
// The main idea is to have a "isMobile" key in the environment, then listen
|
||||||
// to resize events and update the env if needed. Then, the whole interface
|
// to resize events and update the env if needed. Then, the whole interface
|
||||||
// will be updated, creating and destroying widgets as needed.
|
// will be updated, creating and destroying components as needed.
|
||||||
//
|
//
|
||||||
// To see this in action, try resizing the window. The application will switch
|
// To see this in action, try resizing the window. The application will switch
|
||||||
// to mobile mode whenever it has less than 768px.
|
// to mobile mode whenever it has less than 768px.
|
||||||
@@ -921,14 +921,14 @@ const RESPONSIVE = `// In this example, we show how we can modify keys in the gl
|
|||||||
class Navbar extends owl.Component {}
|
class Navbar extends owl.Component {}
|
||||||
|
|
||||||
class ControlPanel extends owl.Component {
|
class ControlPanel extends owl.Component {
|
||||||
widgets = { MobileSearchView };
|
components = { MobileSearchView };
|
||||||
}
|
}
|
||||||
|
|
||||||
class FormView extends owl.Component {
|
class FormView extends owl.Component {
|
||||||
widgets = { AdvancedWidget };
|
components = { AdvancedComponent };
|
||||||
}
|
}
|
||||||
|
|
||||||
class AdvancedWidget extends owl.Component {}
|
class AdvancedComponent extends owl.Component {}
|
||||||
|
|
||||||
class Chatter extends owl.Component {
|
class Chatter extends owl.Component {
|
||||||
messages = Array.from(Array(100).keys());
|
messages = Array.from(Array(100).keys());
|
||||||
@@ -938,7 +938,7 @@ class MobileSearchView extends owl.Component {}
|
|||||||
|
|
||||||
|
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
widgets = { Navbar, ControlPanel, FormView, Chatter };
|
components = { Navbar, ControlPanel, FormView, Chatter };
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -974,12 +974,12 @@ const RESPONSIVE_XML = `<templates>
|
|||||||
|
|
||||||
<div t-name="ControlPanel" class="controlpanel">
|
<div t-name="ControlPanel" class="controlpanel">
|
||||||
<h2>Control Panel</h2>
|
<h2>Control Panel</h2>
|
||||||
<t t-if="env.isMobile" t-widget="MobileSearchView"/>
|
<MobileSearchView t-if="env.isMobile" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="FormView" class="formview">
|
<div t-name="FormView" class="formview">
|
||||||
<h2>Form View</h2>
|
<h2>Form View</h2>
|
||||||
<t t-if="!env.isMobile" t-widget="AdvancedWidget"/>
|
<AdvancedComponent t-if="!env.isMobile" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="Chatter" class="chatter">
|
<div t-name="Chatter" class="chatter">
|
||||||
@@ -989,8 +989,8 @@ const RESPONSIVE_XML = `<templates>
|
|||||||
|
|
||||||
<div t-name="MobileSearchView">Mobile searchview</div>
|
<div t-name="MobileSearchView">Mobile searchview</div>
|
||||||
|
|
||||||
<div t-name="AdvancedWidget">
|
<div t-name="AdvancedComponent">
|
||||||
This widget is only created in desktop mode.
|
This component is only created in desktop mode.
|
||||||
<button>Button!</button>
|
<button>Button!</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1072,7 +1072,7 @@ const RESPONSIVE_CSS = `body {
|
|||||||
const SLOTS = `// We show here how slots can be used to create generic components.
|
const SLOTS = `// We show here how slots can be used to create generic components.
|
||||||
// In this example, the Card component is basically only a container. It is not
|
// In this example, the Card component is basically only a container. It is not
|
||||||
// aware of its content. It just knows where it should be (with t-slot).
|
// aware of its content. It just knows where it should be (with t-slot).
|
||||||
// The parent widget define the content with t-set.
|
// The parent component define the content with t-set.
|
||||||
//
|
//
|
||||||
// Note that the t-on-click event, defined in the App template, is executed in
|
// Note that the t-on-click event, defined in the App template, is executed in
|
||||||
// the context of the App component, even though it is inside the Card component
|
// the context of the App component, even though it is inside the Card component
|
||||||
@@ -1093,9 +1093,9 @@ class Counter extends owl.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main root widget
|
// Main root component
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
widgets = {Card, Counter};
|
components = {Card, Counter};
|
||||||
state = {a: 1, b: 3};
|
state = {a: 1, b: 3};
|
||||||
|
|
||||||
inc(key, delta) {
|
inc(key, delta) {
|
||||||
@@ -1188,13 +1188,13 @@ const SLOTS_CSS = `.main {
|
|||||||
|
|
||||||
const ASYNC_COMPONENTS = `// This example will not work if your browser does not support ESNext class fields
|
const ASYNC_COMPONENTS = `// This example will not work if your browser does not support ESNext class fields
|
||||||
|
|
||||||
// In this example, we have 2 sub widgets, one of them being async (slow).
|
// In this example, we have 2 sub components, one of them being async (slow).
|
||||||
// However, we don't want renderings of the other sub widget to be delayed
|
// However, we don't want renderings of the other sub component to be delayed
|
||||||
// because of the slow widget. We use the 't-asyncroot' directive for this
|
// because of the slow component. We use the 't-asyncroot' directive for this
|
||||||
// purpose. Try removing it to see the difference.
|
// purpose. Try removing it to see the difference.
|
||||||
|
|
||||||
class App extends owl.Component {
|
class App extends owl.Component {
|
||||||
widgets = {SlowWidget, NotificationList};
|
components = {SlowComponent, NotificationList};
|
||||||
state = { value: 0, notifs: [] };
|
state = { value: 0, notifs: [] };
|
||||||
|
|
||||||
increment() {
|
increment() {
|
||||||
@@ -1208,9 +1208,9 @@ class App extends owl.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SlowWidget extends owl.Component {
|
class SlowComponent extends owl.Component {
|
||||||
willUpdateProps() {
|
willUpdateProps() {
|
||||||
// simulate a widget that needs to perform async stuff (e.g. an RPC)
|
// simulate a component that needs to perform async stuff (e.g. an RPC)
|
||||||
// with the updated props before re-rendering itself
|
// with the updated props before re-rendering itself
|
||||||
return new Promise(resolve => setTimeout(resolve, 1500));
|
return new Promise(resolve => setTimeout(resolve, 1500));
|
||||||
}
|
}
|
||||||
@@ -1226,11 +1226,11 @@ app.mount(document.body);
|
|||||||
const ASYNC_COMPONENTS_XML = `<templates>
|
const ASYNC_COMPONENTS_XML = `<templates>
|
||||||
<div t-name="App" class="app">
|
<div t-name="App" class="app">
|
||||||
<button t-on-click="increment">Increment</button>
|
<button t-on-click="increment">Increment</button>
|
||||||
<SlowWidget value="state.value"/>
|
<SlowComponent value="state.value"/>
|
||||||
<NotificationList t-asyncroot="1" notifications="state.notifs"/>
|
<NotificationList t-asyncroot="1" notifications="state.notifs"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div t-name="SlowWidget" class="value" >
|
<div t-name="SlowComponent" class="value" >
|
||||||
Current value: <t t-esc="props.value"/>
|
Current value: <t t-esc="props.value"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user