[REF] component: use 'component' instead of 'widget'

This commit is contained in:
Géry Debongnie
2019-06-20 09:42:33 +02:00
parent 5524c2e323
commit e6a5934162
22 changed files with 553 additions and 586 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ find some more information [here](doc/comparison.md).
## Example
Here is a short example to illustrate interactive widgets:
Here is a short example to illustrate interactive components:
```xml
<templates>
+1 -1
View File
@@ -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:
+4 -4
View File
@@ -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
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)
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
useful for some use cases: for example, a widget may want to fetch an external
library (a calendar widget may need a specialized calendar rendering library),
useful for some use cases: for example, a component may want to fetch an external
library (a calendar component may need a specialized calendar rendering library),
in its willStart hook.
```javascript
class MyCalendarWidget extends owl.Component {
class MyCalendarComponent extends owl.Component {
...
willStart() {
+87 -87
View File
@@ -4,7 +4,7 @@
- [Overview](#overview)
- [Example](#example)
- [Root Widget And Environment](#root-widget-and-environment)
- [Root Component And Environment](#root-component-and-environment)
- [Reference](#reference)
- [Properties](#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
of the application, not as a sequence of imperative steps.
2. **composable:** each widget can seamlessly be created in a parent widget by
a simple directive in its template.
2. **composable:** each component can seamlessly be created in a parent component by
a simple tag or directive in its template.
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.
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
exclusively done by a [QWeb](qweb.md) template (which needs to be preloaded in QWeb).
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
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
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`
directive in a template. There is however an obvious exception: the root 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 component
of an Owl application has to be created manually:
```js
@@ -91,7 +91,7 @@ const app = new App(env);
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
be used to render everything.
@@ -102,7 +102,7 @@ easy to test a component.
## 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
parent to its children. The environment needs to have a QWeb instance, which
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
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
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!!
- **`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
@@ -163,7 +163,7 @@ find a template with the component name (or one of its ancestor).
DOM in the same stack frame.
- **`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
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
@@ -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
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
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
fast as possible.
The widget rendering will take place after `willStart` is completed.
The component rendering will take place after `willStart` is completed.
#### `mounted()`
@@ -296,8 +296,8 @@ scrollbar.
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
DOM state. Also, it will not be called if the widget is not in the DOM (this can
happen with widgets with `t-keepalive`).
DOM state. Also, it will not be called if the component is not in the DOM (this can
happen with components with `t-keepalive`).
The return value of this method will be given as the first argument of the
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
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
not in the DOM (this can happen with widgets with `t-keepalive`).
component was patched. Note that this hook will not be called if the compoent is
not in the DOM (this can happen with components with `t-keepalive`).
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
turn will cause other calls to patched. So, we need to be particularly
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.
```xml
<div t-name="ParentWidget">
<div t-name="ParentComponent">
<span>some text</span>
<MyWidget info="13" />
<MyComponent info="13" />
</div>
```
```js
class ParentWidget extends owl.Component {
widgets = { MyWidget: MyWidget};
class ParentComponent extends owl.Component {
components = { MyComponent: MyComponent};
...
}
```
In this example, the `ParentWidget`'s template creates a widget `MyWidget` just
after the span. The `info` key will be added to the subwidget's `props`. Each
In this example, the `ParentComponent`'s template creates a component `MyComponent` just
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
dynamic. If it is necessary to give a string, this can be done by quoting it:
`someString="'somevalue'"`.
Note that the rendering context for the template is the widget itself. This means
that the template can access `state`, `props`, `env`, or any methods defined in the widget.
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 component.
```xml
<div t-name="ParentWidget">
<ChildWidget count="state.val" />
<div t-name="ParentComponent">
<ChildComponent count="state.val" />
</div>
```
```js
class ParentWidget {
widgets = { ChildWidget };
class ParentComponent {
components = { ChildComponent };
state = { val: 4 };
}
```
Whenever the template is rendered, it will automatically create the subwidget
`ChildWidget` 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
Whenever the template is rendered, it will automatically create the subcomponent
`ChildComponent` at the correct place. It needs to find the reference to the
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
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
on the widget (and also, in the template). Whenever the state is updated, then
the subwidget will also be updated automatically.
on the component (and also, in the template). Whenever the state is updated, then
the sub component will also be updated automatically.
Note that there are some restrictions on prop names: `class`, `style` and any
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
<div t-name="ParentWidget">
<t t-widget="ChildWidget{{id}}" />
<div t-name="ParentComponent">
<t t-component="ChildComponent{{id}}" />
</div>
```
```js
class ParentWidget {
widgets = { ChildWidget1, ChildWidget2 };
class ParentComponent {
components = { ChildComponent1, ChildComponent2 };
state = { id: 1 };
}
```
**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
root widget element.
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 component element.
```xml
<div t-name="ParentWidget">
<MyWidget class="someClass" style="font-weight:bold;" info="13" />
<div t-name="ParentComponent">
<MyComponent class="someClass" style="font-weight:bold;" info="13" />
</div>
```
@@ -425,7 +425,7 @@ class that need to be removed. This is why we only support the explicit syntax
with a class object:
```xml
<MyWidget t-att-class="{a: state.flagA, b: state.flagB}" />
<MyComponent t-att-class="{a: state.flagA, b: state.flagB}" />
```
### 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:
```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
@@ -457,11 +457,11 @@ event.
A _business_ DOM event is triggered by a call to `trigger` on a component.
```xml
<MyWidget t-on-menu-loaded="someMethod" />
<MyComponent t-on-menu-loaded="someMethod" />
```
```js
class MyWidget {
class MyComponent {
someWhere() {
const 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)
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
(in the `detail` property of the event), whenever the event is triggered.
```js
class ParentWidget {
class ParentComponent {
someMethod(ev) {
const payload = ev.detail;
...
@@ -640,7 +640,7 @@ is inserted into the DOM.
```
```js
class MyWidget extends owl.Component {
class MyComponent extends owl.Component {
...
focusMe() {
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.
- widget `B` is created
- component `B` is created
1. `willStart` is called on `B`
2. template `B` is rendered
- widget `C` is created
- component `C` is created
1. `willStart` is called on `C`
2. template `C` is rendered
- widget `D` is created
- component `D` is created
1. `willStart` is called on `D`
2. template `D` is rendered
- widget `E` is created
- component `E` is created
1. `willStart` is called on `E`
2. template `E` is rendered
3. widget `A` is patched into a detached DOM element. This will create the actual
widget `A` DOM structure. The patching process will cause recursively the
3. component `A` is patched into a detached DOM element. This will create the actual
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
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`.
**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`,
- remove `E`,
- add new widget `F`.
- add new component `F`.
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`
2. template `C` is rendered again
- widget `D` is updated:
- component `D` is updated:
1. hook `willUpdateProps` is called on `D` (async)
2. template `D` is rerendered
- widget `F` is created:
- component `F` is created:
1. hook `willStart` is called on `E` (async)
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)
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`,
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
<div>
<div t-ref="someDiv"/>
<SubWidget t-ref="someWidget"/>
<SubComponent t-ref="someComponent"/>
</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:
```js
this.refs.someDiv;
this.refs.someWidget;
this.refs.someComponent;
```
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
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`
variable between `willPatch` and `patched`.
The `t-ref` directive also accepts dynamic values with string interpolation
(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,
```xml
<div t-ref="widget_{{id}}"/>
<div t-ref="component_{{id}}"/>
```
```js
this.refs.widget_44;
this.refs.component_44;
```
### Slots
To make generic components, it is useful to be able for a parent widget to _inject_
some sub template, but still be the owner. For example, a generic dialog widget
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 component
will need to render some content, some footer, but with the parent as the
rendering context.
@@ -886,8 +886,8 @@ This is what _slots_ are for.
Slots are defined by the caller, with the `t-set` directive:
```xml
<div t-name="SomeWidget">
<div>some widget</div>
<div t-name="SomeComponent">
<div>some component</div>
<Dialog title="Some Dialog">
<t t-set="content">
<div>hey</div>
@@ -899,7 +899,7 @@ Slots are defined by the caller, with the `t-set` directive:
</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
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>
```
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:
```xml
@@ -946,23 +946,23 @@ components.
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
- 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.
These changes may be done at different times, and Owl has no way of knowing
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)
synchronous renderings
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
second, and only once (see `owl.utils.loadJS`)
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
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
@@ -972,7 +972,7 @@ Here are a few tips on how to work with asynchronous widgets:
(triggered by state or props changes).
```xml
<div t-name="ParentWidget">
<div t-name="ParentComponent">
<SyncChild />
<AsyncChild t-asyncroot="1"/>
</div>
+4 -4
View File
@@ -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
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
have sub widgets
- a description of the user interface: there should be a root component, which can
have sub components
Here are a few steps that we may take to get started:
- get the templates
- create a qweb engine, with the templates
- create an environment
- create an instance of the root widget
- mount the root widget to a DOM element
- create an instance of the root component
- mount the root component to a DOM element
Let us now add the javascript to make it work, in `app.js`:
+8 -8
View File
@@ -44,7 +44,7 @@ with a few interesting points:
- it compiles templates into functions that output a virtual DOM instead of a
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
@@ -67,7 +67,7 @@ needs. Here is a list of all Owl specific directives:
| 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-key` | [Defining a key (to help virtual dom reconciliation)](component.md#t-key-directive) |
| `t-on-*` | [Event handling](component.md#event-handling) |
@@ -108,7 +108,7 @@ It's API is quite simple:
const TEMPLATES = `
<templates>
<div t-name="App" class="main">main</div>
<div t-name="OtherWidget">other widget</div>
<div t-name="OtherComponent">other component</div>
</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)).
```js
const vnode = qweb.render("App", widget);
const vnode = qweb.render("App", component);
```
- **`register(name, Component)`**: static function to register an OWL Component
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.
```js
@@ -131,8 +131,8 @@ It's API is quite simple:
...
class ParentWidget extends owl.Component { ... }
qweb.addTemplate("ParentWidget", "<div><Dialog/></div>");
class ParentComponent extends owl.Component { ... }
qweb.addTemplate("ParentComponent", "<div><Dialog/></div>");
```
## Reference
@@ -179,7 +179,7 @@ root nodes.
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
widget). For example, `a + b.c(d)` will be converted into:
component). For example, `a + b.c(d)` will be converted into:
```js
context["a"] + context["b"].c(context["d"]);
+27 -27
View File
@@ -42,8 +42,8 @@ export interface Meta<T extends Env, Props> {
isDestroyed: boolean;
parent: Component<T, any, any> | null;
children: { [key: number]: Component<T, any, any> };
// children mapping: from templateID to widgetID
// should it be a map number => Widget?
// children mapping: from templateID to componentID
// should it be a map number => Component?
cmap: { [key: number]: number };
renderId: number;
@@ -62,7 +62,7 @@ export interface Meta<T extends Env, Props> {
const TEMPLATE_MAP: { [key: number]: { [name: string]: string } } = {};
//------------------------------------------------------------------------------
// Widget
// Component
//------------------------------------------------------------------------------
let nextId = 1;
@@ -71,8 +71,8 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
template?: string;
/**
* The `el` is the root element of the widget. Note that it could be null:
* this is the case if the widget is not mounted yet, or is destroyed.
* The `el` is the root element of the component. Note that it could be null:
* this is the case if the component is not mounted yet, or is destroyed.
*/
get el(): HTMLElement | 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.
*
* The root widget of a component tree needs an environment:
* The root component of a component tree needs an environment:
*
* ```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
* 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
* hand. Other widgets should be created automatically by the framework (with
* the t-widget directive in a template)
* Note that most of the time, only the root component needs to be created by
* hand. Other components should be created automatically by the framework (with
* the t-component directive in a template)
*/
constructor(parent: Component<T, any, any> | T, props?: Props) {
const defaultProps = (<any>this.constructor).defaultProps;
@@ -122,9 +122,9 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
this._validateProps(props || {});
}
// 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
// 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>{};
let id: number = nextId++;
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
* 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
* 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
* 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
* turn will cause other calls to updated. So, we need to be particularly
* 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
* - remove the dom node from the dom
*
* This should only be called manually if you created the widget. Most widgets
* will be automatically destroyed.
* This should only be called manually if you created the component. Most
* components will be automatically destroyed.
*/
destroy() {
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 will cause a full rerender of the widget and its children, so this is
* This method is the correct way to update the environment of a component. Doing
* this will cause a full rerender of the component and its children, so this is
* an operation that should not be done frequently.
*
* 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
// 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
// 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
vnode.key = __owl__.id;
__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 {
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() {
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++) {
if (!(propsDef[i] in props)) {
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 (propsDef[propName] && !propsDef[propName].optional) {
throw new Error(
`Missing props '${propName}' (widget '${this.constructor.name}')`
`Missing props '${propName}' (component '${this.constructor.name}')`
);
} else {
break;
@@ -612,7 +612,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
let isValid = isValidProp(props[propName], propsDef[propName]);
if (!isValid) {
throw new Error(
`Props '${propName}' of invalid type in widget '${
`Props '${propName}' of invalid type in component '${
this.constructor.name
}'`
);
+1 -1
View File
@@ -29,7 +29,7 @@ export class EventBus {
* Add a listener for the 'eventType' events.
*
* 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.
*
* Also, the owner should be kind of unique. This will be used to remove the
+6 -6
View File
@@ -130,7 +130,7 @@ let nextID = 1;
export class QWeb {
templates: { [name: string]: Template } = {};
utils = UTILS;
static widgets = Object.create(null);
static components = Object.create(null);
// dev mode enables better error messages or more costly validations
static dev: boolean = false;
@@ -140,7 +140,7 @@ export class QWeb {
// able to map a qweb instance to a template name.
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.
slots = {};
nextSlotId = 1;
@@ -161,10 +161,10 @@ export class QWeb {
}
static register(name: string, Component: any) {
if (QWeb.widgets[name]) {
if (QWeb.components[name]) {
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];
if (firstLetter === firstLetter.toUpperCase()) {
// this is a component, we modify in place the xml document to change
// <SomeComponent ... /> to <t t-widget="SomeComponent" ... />
node.setAttribute('t-widget', node.tagName);
// <SomeComponent ... /> to <t t-component="SomeComponent" ... />
node.setAttribute('t-component', node.tagName);
node.nodeValue = 't';
}
const attributes = (<Element>node).attributes;
+1 -1
View File
@@ -272,7 +272,7 @@ QWeb.addDirective({
let shouldWarn =
nodeCopy.tagName !== "t" && !nodeCopy.hasAttribute("t-key");
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;
}
if (
+71 -71
View File
@@ -10,7 +10,7 @@ import { VNode } from "./vdom";
* - t-on
* - t-ref
* - t-transition
* - t-widget/t-keepalive
* - t-component/t-keepalive
* - t-mounted
* - t-slot
* - 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}"
});
/**
* 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
* you this advice: Good luck...
*
* 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
* 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:
* ```xml
* <Child
@@ -216,23 +216,23 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
*
* ```js
* // we assign utils on top of the function because it will be useful for
* // each widgets
* // each components
* let utils = this.utils;
*
* // this is the virtual node representing the parent div
* let c1 = [], p1 = { key: 1 };
* 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";
*
* // 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...
* 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
* // `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
* // instance
* let w4 =
@@ -240,9 +240,9 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
* ? context.__owl__.children[context.__owl__.cmap[key5]]
* : false;
*
* // We keep the index of the position of the widget in the closure. We push
* // null to reserve the slot, and will replace it later by the widget vnode,
* // when it will be ready (do not forget that preparing/rendering a widget is
* // 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 component vnode,
* // when it will be ready (do not forget that preparing/rendering a component is
* // asynchronous)
* let _2_index = c1.length;
* 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
* 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
* if (w4 && w4.__owl__.renderPromise && !w4.__owl__.vnode) {
* // 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)) {
* def3 = w4.__owl__.renderPromise;
* } 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
* w4.destroy();
* w4 = false;
@@ -268,29 +268,29 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
* }
*
* 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
* // 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) {
* 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);
*
* // Whenever we rerender the parent widget, we need to be sure that we
* // are able to find the widget instance. To do that, we register it to
* // Whenever we rerender the parent component, we need to be sure that we
* // 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
* // 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.
* context.__owl__.cmap[key5] = w4.__owl__.id;
*
* // _prepare is called, to basically call willStart, then render the
* // widget
* // component
* def3 = w4._prepare();
*
* 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
* // the parent's perspective, it simply is a vnode with no children.
* // 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 });
*
* // 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 = {
* 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
* // patch method actually replace the elm by a new elm, so we need
* // to synchronise the pvnode elm with the resulting elm
* let nvn = w4._mount(vnode, vn.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");
* },
* remove() {
@@ -317,7 +317,7 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
* },
* destroy() {
* // 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 = () => {
* w4.destroy();
* };
@@ -328,19 +328,19 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
* c1[_2_index] = pvnode;
*
* // 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;
* });
* } else {
* // 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
* // rendering work (in the case it was rendered with the same props)
* def3 = def3 || w4._updateProps(props4, extra.forceUpdate, extra.patchQueue);
* 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
* // 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.
* if (w4.__owl__.isDestroyed) {
* return;
@@ -360,11 +360,11 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
*/
QWeb.addDirective({
name: "widget",
name: "component",
extraNames: ["props", "keepalive", "asyncroot"],
priority: 100,
atNodeEncounter({ ctx, value, node, qweb }): boolean {
ctx.addLine("//WIDGET");
ctx.addLine("//COMPONENT");
ctx.rootContext.shouldDefineOwner = true;
ctx.rootContext.shouldDefineQWeb = true;
ctx.rootContext.shouldDefineUtils = true;
@@ -408,7 +408,7 @@ QWeb.addDirective({
.join(",");
let dummyID = ctx.generateID();
let defID = ctx.generateID();
let widgetID = ctx.generateID();
let componentID = ctx.generateID();
let keyID = key && ctx.generateID();
if (key) {
// we bind a variable to the key (could be a complex expression, so we
@@ -419,8 +419,8 @@ QWeb.addDirective({
let templateID = key
? `key${keyID}`
: ctx.inLoop
? `String(-${widgetID} - i)`
: String(widgetID);
? `String(-${componentID} - i)`
: String(componentID);
let ref = node.getAttribute("t-ref");
let refExpr = "";
@@ -428,21 +428,21 @@ QWeb.addDirective({
if (ref) {
refKey = `ref${ctx.generateID()}`;
ctx.addLine(`const ${refKey} = ${ctx.interpolate(ref)};`);
refExpr = `context.refs[${refKey}] = w${widgetID};`;
refExpr = `context.refs[${refKey}] = w${componentID};`;
}
let transitionsInsertCode = "";
if (transition) {
transitionsInsertCode = `utils.transitionInsert(vn, '${transition}');`;
}
let finalizeWidgetCode = `w${widgetID}.${
let finalizeComponentCode = `w${componentID}.${
keepAlive ? "unmount" : "destroy"
}();`;
if (ref && !keepAlive) {
finalizeWidgetCode += `delete context.refs[${refKey}];`;
finalizeComponentCode += `delete context.refs[${refKey}];`;
}
if (transition) {
finalizeWidgetCode = `let finalize = () => {
${finalizeWidgetCode}
finalizeComponentCode = `let finalize = () => {
${finalizeComponentCode}
};
utils.transitionRemove(vn, '${transition}', finalize);`;
}
@@ -475,7 +475,7 @@ QWeb.addDirective({
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
.map(function([eventName, mods, handlerName, extraArgs]) {
@@ -487,7 +487,7 @@ QWeb.addDirective({
handler = `function (e) {`;
handler += mods
.map(function(mod) {
return T_WIDGET_MODS_CODE[mod];
return T_COMPONENT_MODS_CODE[mod];
})
.join("");
handler += `owner['${handlerName}'].call(${params}, e);}`;
@@ -503,47 +503,47 @@ QWeb.addDirective({
}
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;`);
if (async) {
ctx.addLine(`const patchQueue${widgetID} = [];`);
ctx.addLine(`const patchQueue${componentID} = [];`);
ctx.addLine(
`c${
ctx.parentNode
}.push(w${widgetID} && w${widgetID}.__owl__.pvnode || null);`
}.push(w${componentID} && w${componentID}.__owl__.pvnode || null);`
);
} else {
ctx.addLine(`c${ctx.parentNode}.push(null);`);
}
ctx.addLine(`let props${widgetID} = {${propStr}};`);
ctx.addLine(`let props${componentID} = {${propStr}};`);
ctx.addIf(
`w${widgetID} && w${widgetID}.__owl__.renderPromise && !w${widgetID}.__owl__.vnode`
`w${componentID} && w${componentID}.__owl__.renderPromise && !w${componentID}.__owl__.vnode`
);
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.addLine(`w${widgetID}.destroy();`);
ctx.addLine(`w${widgetID} = false;`);
ctx.addLine(`w${componentID}.destroy();`);
ctx.addLine(`w${componentID} = false;`);
ctx.closeIf();
ctx.closeIf();
ctx.addIf(`!w${widgetID}`);
// new widget
ctx.addLine(`let widgetKey${widgetID} = ${ctx.interpolate(value)};`);
ctx.addIf(`!w${componentID}`);
// new component
ctx.addLine(`let componentKey${componentID} = ${ctx.interpolate(value)};`);
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...
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(
`context.__owl__.cmap[${templateID}] = w${widgetID}.__owl__.id;`
`context.__owl__.cmap[${templateID}] = w${componentID}.__owl__.id;`
);
// SLOTS
@@ -551,7 +551,7 @@ QWeb.addDirective({
const clone = <Element>node.cloneNode(true);
const slotNodes = clone.querySelectorAll("[t-set]");
const slotId = qweb.nextSlotId++;
ctx.addLine(`w${widgetID}.__owl__.slotId = ${slotId};`);
ctx.addLine(`w${componentID}.__owl__.slotId = ${slotId};`);
if (slotNodes.length) {
for (let i = 0, length = slotNodes.length; i < length; 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
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
}[_${dummyID}_index]=pvnode;w${widgetID}.__owl__.pvnode = pvnode;});`
}[_${dummyID}_index]=pvnode;w${componentID}.__owl__.pvnode = pvnode;});`
);
ctx.addElse();
// need to update widget
const patchQueueCode = async ? `patchQueue${widgetID}` : "extra.patchQueue";
// need to update component
const patchQueueCode = async ? `patchQueue${componentID}` : "extra.patchQueue";
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 = "";
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(
`def${defID} = def${defID}.then(()=>{if (w${widgetID}.__owl__.isDestroyed) {return};${
tattStyle ? `w${widgetID}.el.style=${tattStyle};` : ""
}${updateClassCode}let pvnode=w${widgetID}.__owl__.pvnode;${keepAliveCode}c${
`def${defID} = def${defID}.then(()=>{if (w${componentID}.__owl__.isDestroyed) {return};${
tattStyle ? `w${componentID}.el.style=${tattStyle};` : ""
}${updateClassCode}let pvnode=w${componentID}.__owl__.pvnode;${keepAliveCode}c${
ctx.parentNode
}[_${dummyID}_index]=pvnode;});`
);
@@ -598,7 +598,7 @@ QWeb.addDirective({
if (async) {
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 {
ctx.addLine(`extra.promises.push(def${defID});`);
+9 -9
View File
@@ -9,7 +9,7 @@ exports[`animations t-transition combined with component 1`] = `
var h = this.utils.h;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
let _2_index = c1.length;
@@ -24,9 +24,9 @@ exports[`animations t-transition combined with component 1`] = `
}
}
if (!w4) {
let widgetKey4 = \`Child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`Child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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};
var vn1 = h('div', p1, c1);
if (context['state'].display) {
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
let _2_index = c1.length;
@@ -68,9 +68,9 @@ exports[`animations t-transition combined with t-widget and t-if 1`] = `
}
}
if (!w4) {
let widgetKey4 = \`Child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`Child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
def3 = w4._prepare();
+98 -98
View File
@@ -22,7 +22,7 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = `
let c4 = [], p4 = {key:4,attrs:{class: _3}};
var vn4 = h('div', p4, c4);
c1.push(vn4);
//WIDGET
//COMPONENT
let def6;
let w7 = 7 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[7]] : false;
let _5_index = c4.length;
@@ -37,9 +37,9 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = `
}
}
if (!w7) {
let widgetKey7 = \`Child\`;
let W7 = context.widgets && context.widgets[widgetKey7] || QWeb.widgets[widgetKey7];
if (!W7) {throw new Error('Cannot find the definition of widget \\"' + widgetKey7 + '\\"')}
let componentKey7 = \`Child\`;
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
w7 = new W7(owner, props7);
context.__owl__.cmap[7] = w7.__owl__.id;
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;});
}
extra.promises.push(def6);
//WIDGET
//COMPONENT
let def9;
let w10 = 10 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[10]] : false;
let _8_index = c4.length;
@@ -65,9 +65,9 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = `
}
}
if (!w10) {
let widgetKey10 = \`AsyncChild\`;
let W10 = context.widgets && context.widgets[widgetKey10] || QWeb.widgets[widgetKey10];
if (!W10) {throw new Error('Cannot find the definition of widget \\"' + widgetKey10 + '\\"')}
let componentKey10 = \`AsyncChild\`;
let W10 = context.components && context.components[componentKey10] || QWeb.components[componentKey10];
if (!W10) {throw new Error('Cannot find the definition of component \\"' + componentKey10 + '\\"')}
w10 = new W10(owner, props10);
context.__owl__.cmap[10] = w10.__owl__.id;
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}};
var vn4 = h('div', p4, c4);
c1.push(vn4);
//WIDGET
//COMPONENT
let def6;
let w7 = 7 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[7]] : false;
let _5_index = c4.length;
@@ -119,9 +119,9 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = `
}
}
if (!w7) {
let widgetKey7 = \`Child\`;
let W7 = context.widgets && context.widgets[widgetKey7] || QWeb.widgets[widgetKey7];
if (!W7) {throw new Error('Cannot find the definition of widget \\"' + widgetKey7 + '\\"')}
let componentKey7 = \`Child\`;
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
w7 = new W7(owner, props7);
context.__owl__.cmap[7] = w7.__owl__.id;
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.then(w7._applyPatchQueue.bind(w7, patchQueue7));
//WIDGET
//COMPONENT
let def9;
let w10 = 10 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[10]] : false;
let _8_index = c4.length;
@@ -146,9 +146,9 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = `
}
}
if (!w10) {
let widgetKey10 = \`AsyncChild\`;
let W10 = context.widgets && context.widgets[widgetKey10] || QWeb.widgets[widgetKey10];
if (!W10) {throw new Error('Cannot find the definition of widget \\"' + widgetKey10 + '\\"')}
let componentKey10 = \`AsyncChild\`;
let W10 = context.components && context.components[componentKey10] || QWeb.components[componentKey10];
if (!W10) {throw new Error('Cannot find the definition of component \\"' + componentKey10 + '\\"')}
w10 = new W10(owner, props10);
context.__owl__.cmap[10] = w10.__owl__.id;
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
) {
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}};
var vn4 = h('div', p4, c4);
c1.push(vn4);
//WIDGET
//COMPONENT
let def6;
let w7 = 7 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[7]] : false;
let _5_index = c4.length;
@@ -199,9 +199,9 @@ exports[`async rendering t-widget with t-asyncroot directive: mixed re-rendering
}
}
if (!w7) {
let widgetKey7 = \`Child\`;
let W7 = context.widgets && context.widgets[widgetKey7] || QWeb.widgets[widgetKey7];
if (!W7) {throw new Error('Cannot find the definition of widget \\"' + widgetKey7 + '\\"')}
let componentKey7 = \`Child\`;
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
w7 = new W7(owner, props7);
context.__owl__.cmap[7] = w7.__owl__.id;
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;});
}
extra.promises.push(def6);
//WIDGET
//COMPONENT
let def9;
let w10 = 10 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[10]] : false;
let _8_index = c4.length;
@@ -227,9 +227,9 @@ exports[`async rendering t-widget with t-asyncroot directive: mixed re-rendering
}
}
if (!w10) {
let widgetKey10 = \`AsyncChild\`;
let W10 = context.widgets && context.widgets[widgetKey10] || QWeb.widgets[widgetKey10];
if (!W10) {throw new Error('Cannot find the definition of widget \\"' + widgetKey10 + '\\"')}
let componentKey10 = \`AsyncChild\`;
let W10 = context.components && context.components[componentKey10] || QWeb.components[componentKey10];
if (!W10) {throw new Error('Cannot find the definition of component \\"' + componentKey10 + '\\"')}
w10 = new W10(owner, props10);
context.__owl__.cmap[10] = w10.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
const _5 = context['state'].style;
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) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
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;
@@ -309,9 +309,9 @@ exports[`class and style attributes with t-widget t-att-class is properly added/
}
}
if (!w4) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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 = _3[i];
context.number_value = _4[i];
//WIDGET
//COMPONENT
let key8 = context['number'];
let def6;
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) {
let widgetKey7 = \`ChildWidget\`;
let W7 = context.widgets && context.widgets[widgetKey7] || QWeb.widgets[widgetKey7];
if (!W7) {throw new Error('Cannot find the definition of widget \\"' + widgetKey7 + '\\"')}
let componentKey7 = \`ChildWidget\`;
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
w7 = new W7(owner, props7);
context.__owl__.cmap[key8] = w7.__owl__.id;
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
) {
let utils = this.utils;
@@ -395,7 +395,7 @@ exports[`composition t-widget with dynamic value 1`] = `
var h = this.utils.h;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
let _2_index = c1.length;
@@ -410,9 +410,9 @@ exports[`composition t-widget with dynamic value 1`] = `
}
}
if (!w4) {
let widgetKey4 = (context['state'].widget);
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = (context['state'].widget);
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
let utils = this.utils;
@@ -435,7 +435,7 @@ exports[`composition t-widget with dynamic value 2 1`] = `
var h = this.utils.h;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
let _2_index = c1.length;
@@ -450,9 +450,9 @@ exports[`composition t-widget with dynamic value 2 1`] = `
}
}
if (!w4) {
let widgetKey4 = \`Widget\${context['state'].widget}\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`Widget\${context['state'].widget}\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
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) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
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) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
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) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
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) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
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) {
let widgetKey4 = \`Child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`Child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
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) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
let _2_index = c1.length;
@@ -730,9 +730,9 @@ exports[`other directives with t-widget t-on with self modifier 1`] = `
}
}
if (!w4) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
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
) {
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;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
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) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
def3 = w4._prepare();
@@ -795,7 +795,7 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = `
var h = this.utils.h;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let key5 = 'somestring';
let def3;
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) {
let widgetKey4 = \`child\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[key5] = w4.__owl__.id;
def3 = w4._prepare();
@@ -983,7 +983,7 @@ exports[`t-slot directive can define and call slots 1`] = `
var h = this.utils.h;
let c1 = [], p1 = {key:1};
var vn1 = h('div', p1, c1);
//WIDGET
//COMPONENT
let def3;
let w4 = 4 in context.__owl__.cmap ? context.__owl__.children[context.__owl__.cmap[4]] : false;
let _2_index = c1.length;
@@ -998,9 +998,9 @@ exports[`t-slot directive can define and call slots 1`] = `
}
}
if (!w4) {
let widgetKey4 = \`Dialog\`;
let W4 = context.widgets && context.widgets[widgetKey4] || QWeb.widgets[widgetKey4];
if (!W4) {throw new Error('Cannot find the definition of widget \\"' + widgetKey4 + '\\"')}
let componentKey4 = \`Dialog\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(owner, props4);
context.__owl__.cmap[4] = w4.__owl__.id;
w4.__owl__.slotId = 1;
-33
View File
@@ -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);
}
}
+8 -8
View File
@@ -18,7 +18,7 @@ import {
// - fixture: a div, appended to the DOM, intended to be the target of dom
// manipulations. Note that it is removed after each test.
// - 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
let fixture: HTMLElement;
@@ -179,7 +179,7 @@ describe("animations", () => {
);
env.qweb.addTemplate("Child", `<span>blue</span>`);
class Parent extends Widget {
widgets = { Child: Child };
components = { Child: Child };
}
class Child extends Widget {}
const widget = new Parent(env);
@@ -209,16 +209,16 @@ describe("animations", () => {
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);
env.qweb.addTemplate(
"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>`);
class Parent extends Widget {
widgets = { Child: Child };
components = { Child: Child };
state = { display: true };
}
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);
env.qweb.addTemplates(
`<templates>
<div t-name="Parent">
<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>
<span t-name="Child">blue</span>
</templates>`
);
class Child extends Widget {}
class Parent extends Widget {
widgets = { Child };
components = { Child };
constructor(parent) {
super(parent);
this.state = { flag: false };
+171 -171
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -54,7 +54,7 @@ describe("props validation", () => {
try {
await w._updateProps({});
} 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(() => {
new TestWidget(env);
}).toThrow("Missing props 'message' (widget 'TestWidget')");
}).toThrow("Missing props 'message' (component 'TestWidget')");
});
test("validate simple types", async () => {
@@ -93,7 +93,7 @@ describe("props validation", () => {
expect(() => {
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(() => {
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(() => {
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 () => {
+10 -10
View File
@@ -541,7 +541,7 @@ describe("connecting a component to store", () => {
);
env.qweb.addTemplate("Todo", `<span><t t-esc="props.msg"/></span>`);
class App extends Component<any, any, any> {
widgets = { Todo };
components = { Todo };
}
class Todo extends Component<any, any, any> {}
const state = { todos: [] };
@@ -632,7 +632,7 @@ describe("connecting a component to store", () => {
</templates>
`);
class App extends Component<any, any, any> {
widgets = { Todo };
components = { Todo };
}
class Todo extends Component<any, any, any> {}
@@ -686,11 +686,11 @@ describe("connecting a component to store", () => {
"Parent",
`
<div>
<t t-if="state.child" t-widget="ConnectedChild"/>
<t t-if="state.child" t-component="ConnectedChild"/>
</div>`
);
class Parent extends Component<any, any, any> {
widgets = { ConnectedChild };
components = { ConnectedChild };
constructor(env: Env) {
super(env);
@@ -739,7 +739,7 @@ describe("connecting a component to store", () => {
</div>`
);
class TodoList extends Component<any, any, any> {
widgets = { ConnectedTodo };
components = { ConnectedTodo };
}
function mapStoreToProps(state) {
@@ -806,7 +806,7 @@ describe("connecting a component to store", () => {
</div>`
);
class TodoList extends Component<any, any, any> {
widgets = { ConnectedTodo };
components = { ConnectedTodo };
}
function mapStoreToProps(state) {
@@ -843,7 +843,7 @@ describe("connecting a component to store", () => {
</div>`
);
class App extends Component<any, any, any> {
widgets = { ConnectedBeer };
components = { ConnectedBeer };
state = { beerId: 1 };
}
@@ -927,7 +927,7 @@ describe("connecting a component to store", () => {
</div>`
);
class App extends Component<any, any, any> {
widgets = { ConnectedBeer };
components = { ConnectedBeer };
state = { beerId: 0 };
}
@@ -999,7 +999,7 @@ describe("connecting a component to store", () => {
</div>`
);
class App extends Component<any, any, any> {
widgets = { ConnectedBeer };
components = { ConnectedBeer };
state = { beerId: 0 };
}
@@ -1079,7 +1079,7 @@ describe("connecting a component to store", () => {
`
);
class Parent extends Component<any, any, any> {
widgets = { Child: ConnectedChild };
components = { Child: ConnectedChild };
}
const ConnectedParent = connect(
Parent,
+2 -2
View File
@@ -20,7 +20,7 @@ class Counter extends owl.Component {
// Message Widget
//------------------------------------------------------------------------------
class Message extends owl.Component {
widgets = { Counter };
components = { Counter };
shouldUpdate(nextProps) {
return nextProps.message !== this.props.message;
@@ -36,7 +36,7 @@ class Message extends owl.Component {
// Root Widget
//------------------------------------------------------------------------------
class App extends owl.Component {
widgets = { Message };
components = { Message };
state = { messages: [], multipleFlag: false, clearAfterFlag: false };
mounted() {
+2 -2
View File
@@ -30,7 +30,7 @@
<div class="right-thing">
<div class="content" t-on-remove-message="removeMessage">
<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>
</div>
</div>
@@ -40,7 +40,7 @@
<span class="author"><t t-esc="props.message.author"/></span>
<span class="msg"><t t-esc="props.message.msg"/></span>
<button class="remove" t-on-click="removeMessage">Remove</button>
<t t-widget="Counter"/>
<Counter/>
</div>
<div t-name="Counter">
+1 -1
View File
@@ -161,7 +161,7 @@ class App extends owl.Component {
super(...args);
this.version = owl.__info__.version;
this.SAMPLES = SAMPLES;
this.widgets = { TabbedEditor };
this.components = { TabbedEditor };
this.state = {
js: SAMPLES[0].code,
+36 -36
View File
@@ -8,9 +8,9 @@ class Counter extends owl.Component {
}
}
// Main root widget
// Main root component
class App extends owl.Component {
widgets = { Counter };
components = { Counter };
}
// Application setup
@@ -49,8 +49,8 @@ class Counter extends owl.Component {
}
class App extends owl.Component {
state = { flag: false, widgetFlag: false, numbers: [] };
widgets = { Counter };
state = { flag: false, componentFlag: false, numbers: [] };
components = { Counter };
toggle(key) {
this.state[key] = !this.state[key];
@@ -83,12 +83,12 @@ const ANIMATION_XML = `<templates>
</div>
</div>
<h2>Transition on sub widgets</h2>
<h2>Transition on sub components</h2>
<div class="demo">
<button t-on-click="toggle('widgetFlag')">Toggle widget</button>
<button t-on-click="toggle('componentFlag')">Toggle component</button>
<div>
<Counter t-if="state.widgetFlag" t-transition="fade"/>
<Counter t-if="state.componentFlag" t-transition="fade"/>
</div>
</div>
@@ -173,12 +173,12 @@ const ANIMATION_CSS = `button {
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
// clicking on the two main buttons, and look into the console to see what
// happens.
class DemoWidget extends owl.Component {
class DemoComponent extends owl.Component {
constructor() {
super(...arguments);
this.state = { n: 0 };
@@ -208,14 +208,14 @@ class DemoWidget extends owl.Component {
}
class App extends owl.Component {
widgets = { DemoWidget };
components = { DemoComponent };
state = { n: 0, flag: true };
increment() {
this.state.n++;
}
toggleSubWidget() {
toggleSubComponent() {
this.state.flag = !this.state.flag;
}
}
@@ -226,17 +226,17 @@ app.mount(document.body);
`;
const LIFECYCLE_DEMO_XML = `<templates>
<div t-name="DemoWidget" t-on-click="increment" class="demo">
<div>Demo Sub Widget</div>
<div t-name="DemoComponent" t-on-click="increment" class="demo">
<div>Demo Sub Component</div>
<div>(click on me to update me)</div>
<div>Props: <t t-esc="props.n"/>, State: <t t-esc="state.n"/>. </div>
</div>
<div t-name="App">
<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">
<DemoWidget n="state.n"/>
<DemoComponent n="state.n"/>
</div>
</div>
</templates>`;
@@ -406,7 +406,7 @@ function mapStoreToProps(state) {
}
class TodoApp extends owl.Component {
widgets = { TodoItem };
components = { TodoItem };
state = { filter: "all" };
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
// 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 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 ControlPanel extends owl.Component {
widgets = { MobileSearchView };
components = { MobileSearchView };
}
class FormView extends owl.Component {
widgets = { AdvancedWidget };
components = { AdvancedComponent };
}
class AdvancedWidget extends owl.Component {}
class AdvancedComponent extends owl.Component {}
class Chatter extends owl.Component {
messages = Array.from(Array(100).keys());
@@ -938,7 +938,7 @@ class MobileSearchView 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">
<h2>Control Panel</h2>
<t t-if="env.isMobile" t-widget="MobileSearchView"/>
<MobileSearchView t-if="env.isMobile" />
</div>
<div t-name="FormView" class="formview">
<h2>Form View</h2>
<t t-if="!env.isMobile" t-widget="AdvancedWidget"/>
<AdvancedComponent t-if="!env.isMobile" />
</div>
<div t-name="Chatter" class="chatter">
@@ -989,8 +989,8 @@ const RESPONSIVE_XML = `<templates>
<div t-name="MobileSearchView">Mobile searchview</div>
<div t-name="AdvancedWidget">
This widget is only created in desktop mode.
<div t-name="AdvancedComponent">
This component is only created in desktop mode.
<button>Button!</button>
</div>
@@ -1072,7 +1072,7 @@ const RESPONSIVE_CSS = `body {
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
// 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
// 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 {
widgets = {Card, Counter};
components = {Card, Counter};
state = {a: 1, b: 3};
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
// In this example, we have 2 sub widgets, one of them being async (slow).
// However, we don't want renderings of the other sub widget to be delayed
// because of the slow widget. We use the 't-asyncroot' directive for this
// In this example, we have 2 sub components, one of them being async (slow).
// However, we don't want renderings of the other sub component to be delayed
// because of the slow component. We use the 't-asyncroot' directive for this
// purpose. Try removing it to see the difference.
class App extends owl.Component {
widgets = {SlowWidget, NotificationList};
components = {SlowComponent, NotificationList};
state = { value: 0, notifs: [] };
increment() {
@@ -1208,9 +1208,9 @@ class App extends owl.Component {
}
}
class SlowWidget extends owl.Component {
class SlowComponent extends owl.Component {
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
return new Promise(resolve => setTimeout(resolve, 1500));
}
@@ -1226,11 +1226,11 @@ app.mount(document.body);
const ASYNC_COMPONENTS_XML = `<templates>
<div t-name="App" class="app">
<button t-on-click="increment">Increment</button>
<SlowWidget value="state.value"/>
<SlowComponent value="state.value"/>
<NotificationList t-asyncroot="1" notifications="state.notifs"/>
</div>
<div t-name="SlowWidget" class="value" >
<div t-name="SlowComponent" class="value" >
Current value: <t t-esc="props.value"/>
</div>