mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
+27
-33
@@ -337,15 +337,14 @@ This is the opposite method of `mounted`.
|
||||
|
||||
### Composition
|
||||
|
||||
The example above shows a QWeb template with a `t-on-click` directive. Widget
|
||||
templates are standard [QWeb](qweb.md) templates, but with an extra directive:
|
||||
`t-widget`. With the `t-widget` directive, widget templates can declare sub
|
||||
widgets:
|
||||
The example above shows a QWeb template with a sub component. In a template,
|
||||
components are declared with a tagname corresponding to the class name. It has
|
||||
to be capitalized.
|
||||
|
||||
```xml
|
||||
<div t-name="ParentWidget">
|
||||
<span>some text</span>
|
||||
<t t-widget="MyWidget" info="13"/>
|
||||
<MyWidget info="13" />
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -357,22 +356,18 @@ class ParentWidget extends owl.Component {
|
||||
```
|
||||
|
||||
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
|
||||
props is a string which represents a javascript (QWeb) expression, so it is
|
||||
after the span. The `info` key will be added to the subwidget'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'"`. See the
|
||||
[QWeb](qweb.md) documentation for more information on the `t-widget` directive.
|
||||
`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.
|
||||
|
||||
The `t-widget` directive is the key to a declarative component
|
||||
system. It allows a template to define where and how a sub widget is created
|
||||
and/or updated. For example:
|
||||
|
||||
```xml
|
||||
<div t-name="ParentWidget">
|
||||
<t t-widget="ChildWidget" count="state.val"/>
|
||||
<ChildWidget count="state.val" />
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -397,12 +392,11 @@ the subwidget 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 also accepts dynamic values with string interpolation
|
||||
(like the [`t-attf-`](qweb.md#dynamic-attributes) directive):
|
||||
The `t-widget` 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}}"/>
|
||||
<t t-widget="ChildWidget{{id}}" />
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -419,7 +413,7 @@ root widget element.
|
||||
|
||||
```xml
|
||||
<div t-name="ParentWidget">
|
||||
<t t-widget="MyWidget" class="someClass" style="font-weight:bold;" info="13"/>
|
||||
<MyWidget class="someClass" style="font-weight:bold;" info="13" />
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -431,7 +425,7 @@ class that need to be removed. This is why we only support the explicit syntax
|
||||
with a class object:
|
||||
|
||||
```xml
|
||||
<t t-widget="MyWidget" t-att-class="{a: state.flagA, b: state.flagB}" />
|
||||
<MyWidget t-att-class="{a: state.flagA, b: state.flagB}" />
|
||||
```
|
||||
|
||||
### Event Handling
|
||||
@@ -463,7 +457,7 @@ event.
|
||||
A _business_ DOM event is triggered by a call to `trigger` on a component.
|
||||
|
||||
```xml
|
||||
<t t-widget="MyWidget" t-on-menu-loaded="someMethod"/>
|
||||
<MyWidget t-on-menu-loaded="someMethod" />
|
||||
```
|
||||
|
||||
```js
|
||||
@@ -538,8 +532,8 @@ class Form extends owl.Component {
|
||||
|
||||
```xml
|
||||
<div>
|
||||
<input t-on-input="_updateInputValue"/>
|
||||
<span t-esc="state.text"/>
|
||||
<input t-on-input="_updateInputValue" />
|
||||
<span t-esc="state.text" />
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -559,8 +553,8 @@ class Form extends owl.Component {
|
||||
|
||||
```xml
|
||||
<div>
|
||||
<input t-model="text"/>
|
||||
<span t-esc="state.text"/>
|
||||
<input t-model="text" />
|
||||
<span t-esc="state.text" />
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -586,7 +580,7 @@ The `t-model` directive works with `<input>`, `<input type="checkbox">`,
|
||||
<label for="red">Red</label>
|
||||
</span>
|
||||
<span>
|
||||
<input type="radio" name="color" id="blue" value="blue" t-model="color"/>
|
||||
<input type="radio" name="color" id="blue" value="blue" t-model="color" />
|
||||
<label for="blue">Blue</label>
|
||||
</span>
|
||||
</div>
|
||||
@@ -604,7 +598,7 @@ Like event handling, the `t-model` directive accepts some modifiers:
|
||||
For example:
|
||||
|
||||
```xml
|
||||
<input t-model.lazy="someVal"/>
|
||||
<input t-model.lazy="someVal" />
|
||||
```
|
||||
|
||||
These modifiers can be combined. For instance, `t-model.lazy.number` will only
|
||||
@@ -627,7 +621,7 @@ There are three main use cases:
|
||||
|
||||
```xml
|
||||
<span t-foreach="todos" t-as="todo" t-key="todo.id">
|
||||
<t t-esc="todo.text"/>
|
||||
<t t-esc="todo.text" />
|
||||
</span>
|
||||
```
|
||||
|
||||
@@ -836,7 +830,7 @@ Like the `t-on` directive, it can work either on a DOM node, or on a component:
|
||||
```xml
|
||||
<div>
|
||||
<div t-ref="someDiv"/>
|
||||
<t t-widget="SubWidget" t-ref="someWidget"/>
|
||||
<SubWidget t-ref="someWidget"/>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -894,14 +888,14 @@ Slots are defined by the caller, with the `t-set` directive:
|
||||
```xml
|
||||
<div t-name="SomeWidget">
|
||||
<div>some widget</div>
|
||||
<t t-widget="Dialog" title="Some Dialog">
|
||||
<Dialog title="Some Dialog">
|
||||
<t t-set="content">
|
||||
<div>hey</div>
|
||||
</t>
|
||||
<t t-set="footer">
|
||||
<button t-on-click="doSomething">ok</button>
|
||||
</t>
|
||||
</t>
|
||||
</Dialog>
|
||||
</div>
|
||||
```
|
||||
|
||||
@@ -933,9 +927,9 @@ be considered the `default` slot. For example:
|
||||
|
||||
```xml
|
||||
<div t-name="Parent">
|
||||
<t t-widget="Child">
|
||||
<Child>
|
||||
<span>some content</span>
|
||||
</t>
|
||||
</Child>
|
||||
</div>
|
||||
|
||||
<div t-name="Child">
|
||||
@@ -979,7 +973,7 @@ Here are a few tips on how to work with asynchronous widgets:
|
||||
|
||||
```xml
|
||||
<div t-name="ParentWidget">
|
||||
<t t-widget="SyncChild"/>
|
||||
<t t-widget="AsyncChild" t-asyncroot="1"/>
|
||||
<SyncChild />
|
||||
<AsyncChild t-asyncroot="1"/>
|
||||
</div>
|
||||
```
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ It's API is quite simple:
|
||||
...
|
||||
|
||||
class ParentWidget extends owl.Component { ... }
|
||||
qweb.addTemplate("ParentWidget", "<div><t t-widget='Dialog'/></div>");
|
||||
qweb.addTemplate("ParentWidget", "<div><Dialog/></div>");
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
@@ -346,6 +346,13 @@ export class QWeb {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
node.nodeValue = 't';
|
||||
}
|
||||
const attributes = (<Element>node).attributes;
|
||||
|
||||
const validDirectives: {
|
||||
|
||||
@@ -208,7 +208,7 @@ const T_WIDGET_MODS_CODE = Object.assign({}, MODS_CODE, {
|
||||
* explanation of the code generated by the t-widget directive for the following
|
||||
* situation:
|
||||
* ```xml
|
||||
* <t t-widget="child"
|
||||
* <Child
|
||||
* t-key="'somestring'"
|
||||
* flag="state.flag"
|
||||
* t-transition="fade"/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`animations t-transition combined with t-widget 1`] = `
|
||||
exports[`animations t-transition combined with component 1`] = `
|
||||
"function anonymous(context,extra
|
||||
) {
|
||||
let utils = this.utils;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`async rendering delayed t-widget with t-asyncroot directive 1`] = `
|
||||
exports[`async rendering delayed component with t-asyncroot directive 1`] = `
|
||||
"function anonymous(context,extra
|
||||
) {
|
||||
let utils = this.utils;
|
||||
@@ -81,7 +81,7 @@ exports[`async rendering delayed t-widget with t-asyncroot directive 1`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`async rendering fast t-widget with t-asyncroot directive 1`] = `
|
||||
exports[`async rendering fast component with t-asyncroot directive 1`] = `
|
||||
"function anonymous(context,extra
|
||||
) {
|
||||
let utils = this.utils;
|
||||
@@ -650,7 +650,7 @@ exports[`other directives with t-widget t-on with prevent and self modifiers (or
|
||||
}
|
||||
}
|
||||
if (!w4) {
|
||||
let widgetKey4 = \`child\`;
|
||||
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 + '\\"')}
|
||||
w4 = new W4(owner, props4);
|
||||
|
||||
@@ -170,12 +170,12 @@ describe("animations", () => {
|
||||
expect(spanNode.className).toBe("");
|
||||
});
|
||||
|
||||
test("t-transition combined with t-widget", async () => {
|
||||
test("t-transition combined with component", async () => {
|
||||
expect.assertions(5);
|
||||
|
||||
env.qweb.addTemplate(
|
||||
"Parent",
|
||||
`<div><t t-widget="Child" t-transition="chimay"/></div>`
|
||||
`<div><Child t-transition="chimay"/></div>`
|
||||
);
|
||||
env.qweb.addTemplate("Child", `<span>blue</span>`);
|
||||
class Parent extends Widget {
|
||||
|
||||
+65
-50
@@ -468,7 +468,7 @@ describe("lifecycle hooks", () => {
|
||||
`
|
||||
<div>
|
||||
<div t-if="state.flag">
|
||||
<t t-widget="ChildWidget" n="state.n"/>
|
||||
<ChildWidget n="state.n"/>
|
||||
</div>
|
||||
</div>`
|
||||
);
|
||||
@@ -549,7 +549,7 @@ describe("lifecycle hooks", () => {
|
||||
let def = makeDeferred();
|
||||
env.qweb.addTemplate(
|
||||
"Parent",
|
||||
'<span><t t-widget="Child" n="state.n"/></span>'
|
||||
'<span><Child n="state.n"/></span>'
|
||||
);
|
||||
class Parent extends Widget {
|
||||
state = { n: 1 };
|
||||
@@ -601,7 +601,7 @@ describe("lifecycle hooks", () => {
|
||||
|
||||
env.qweb.addTemplate(
|
||||
"Parent",
|
||||
'<div><t t-widget="Child" a="state.a"/></div>'
|
||||
'<div><Child a="state.a"/></div>'
|
||||
);
|
||||
class Parent extends Widget {
|
||||
state = { a: 1 };
|
||||
@@ -644,7 +644,7 @@ describe("lifecycle hooks", () => {
|
||||
let shouldUpdate = false;
|
||||
env.qweb.addTemplate(
|
||||
"Parent",
|
||||
`<div><t t-widget="Child" val="state.val"/></div>`
|
||||
`<div><Child val="state.val"/></div>`
|
||||
);
|
||||
class Parent extends Widget {
|
||||
state = { val: 42 };
|
||||
@@ -889,11 +889,26 @@ describe("composition", () => {
|
||||
delete QWeb.widgets["WidgetB"];
|
||||
});
|
||||
|
||||
test("can define widgets in template without t-widget", async () => {
|
||||
env.qweb.addTemplates(`
|
||||
<templates>
|
||||
<div t-name="P"><C a="1"/></div>
|
||||
<span t-name="C"><t t-esc="props.a"/></span>
|
||||
</templates>`);
|
||||
class C extends Widget {}
|
||||
class P extends Widget {
|
||||
widgets = {C};
|
||||
}
|
||||
const parent = new P(env);
|
||||
await parent.mount(fixture);
|
||||
expect(fixture.innerHTML).toBe("<div><span>1</span></div>");
|
||||
});
|
||||
|
||||
test("throw a nice error if it cannot find widget", async () => {
|
||||
expect.assertions(1);
|
||||
env.qweb.addTemplate(
|
||||
"Parent",
|
||||
`<div><t t-widget="SomeMispelledWidget"/></div>`
|
||||
`<div><SomeMispelledWidget /></div>`
|
||||
);
|
||||
class Parent extends Widget {
|
||||
widgets = { SomeWidget: Widget };
|
||||
@@ -1074,11 +1089,11 @@ describe("composition", () => {
|
||||
test("sub widgets are destroyed if no longer in dom, then recreated", async () => {
|
||||
env.qweb.addTemplate(
|
||||
"ParentWidget",
|
||||
`<div><t t-if="state.ok"><t t-widget="counter"/></t></div>`
|
||||
`<div><t t-if="state.ok"><Counter /></t></div>`
|
||||
);
|
||||
class ParentWidget extends Widget {
|
||||
state = { ok: true };
|
||||
widgets = { counter: Counter };
|
||||
widgets = { Counter };
|
||||
}
|
||||
const widget = new ParentWidget(env);
|
||||
await widget.mount(fixture);
|
||||
@@ -1102,11 +1117,11 @@ describe("composition", () => {
|
||||
test("sub widgets with t-keepalive are not destroyed if no longer in dom", async () => {
|
||||
env.qweb.addTemplate(
|
||||
"ParentWidget",
|
||||
`<div><t t-if="state.ok"><t t-widget="counter" t-keepalive="1"/></t></div>`
|
||||
`<div><t t-if="state.ok"><Counter t-keepalive="1"/></t></div>`
|
||||
);
|
||||
class ParentWidget extends Widget {
|
||||
state = { ok: true };
|
||||
widgets = { counter: Counter };
|
||||
widgets = { Counter };
|
||||
}
|
||||
const widget = new ParentWidget(env);
|
||||
await widget.mount(fixture);
|
||||
@@ -1135,7 +1150,7 @@ describe("composition", () => {
|
||||
test("sub widgets dom state with t-keepalive is preserved", async () => {
|
||||
env.qweb.addTemplate(
|
||||
"ParentWidget",
|
||||
`<div><t t-if="state.ok"><t t-widget="InputWidget" t-keepalive="1"/></t></div>`
|
||||
`<div><t t-if="state.ok"><InputWidget t-keepalive="1"/></t></div>`
|
||||
);
|
||||
class ParentWidget extends Widget {
|
||||
state = { ok: true };
|
||||
@@ -1163,7 +1178,7 @@ describe("composition", () => {
|
||||
env.qweb.addTemplates(`
|
||||
<templates>
|
||||
<div t-name="ParentWidget">
|
||||
<t t-if="state.ok"><t t-widget="ChildWidget" t-ref="child" t-keepalive="1"/></t>
|
||||
<t t-if="state.ok"><ChildWidget t-ref="child" t-keepalive="1"/></t>
|
||||
</div>
|
||||
<span t-name="ChildWidget">Hello</span>
|
||||
</templates>`);
|
||||
@@ -1275,7 +1290,7 @@ describe("composition", () => {
|
||||
`<div>
|
||||
<h1 t-if="state.flag">hey</h1>
|
||||
<h2 t-else="1">noo</h2>
|
||||
<span><t t-widget="ChildWidget"/></span>
|
||||
<span><ChildWidget/></span>
|
||||
<t t-if="state.flag"><span>test</span></t>
|
||||
</div>`
|
||||
);
|
||||
@@ -1723,18 +1738,18 @@ describe("other directives with t-widget", () => {
|
||||
env.qweb.addTemplates(`
|
||||
<templates>
|
||||
<div t-name="ParentWidget">
|
||||
<t t-widget="child" t-on-ev.prevent.self="onEv"/>
|
||||
<Child t-on-ev.prevent.self="onEv"/>
|
||||
</div>
|
||||
<div t-name="Child"><t t-widget="child"/></div>
|
||||
<div t-name="Child"><GrandChild/></div>
|
||||
</templates>
|
||||
`);
|
||||
const steps: boolean[] = [];
|
||||
class ParentWidget extends Widget {
|
||||
widgets = { child: Child };
|
||||
widgets = { Child };
|
||||
onEv() {}
|
||||
}
|
||||
class Child extends Widget {
|
||||
widgets = { child: GrandChild };
|
||||
widgets = { GrandChild };
|
||||
}
|
||||
class GrandChild extends Widget {}
|
||||
const widget = new ParentWidget(env);
|
||||
@@ -1962,7 +1977,7 @@ describe("random stuff/miscellaneous", () => {
|
||||
steps.push(`${this.name}:destroy`);
|
||||
}
|
||||
}
|
||||
env.qweb.addTemplate("A", `<div>A<t t-widget="B"/><t t-widget="C"/></div>`);
|
||||
env.qweb.addTemplate("A", `<div>A<B /><C /></div>`);
|
||||
class A extends TestWidget {
|
||||
widgets = { B, C };
|
||||
name = "A";
|
||||
@@ -1978,9 +1993,9 @@ describe("random stuff/miscellaneous", () => {
|
||||
env.qweb.addTemplate(
|
||||
"C",
|
||||
`
|
||||
<div>C<t t-widget="D"/>
|
||||
<t t-if="state.flag" t-widget="E"/>
|
||||
<t t-else="!state.flag" t-widget="F"/>
|
||||
<div>C<D />
|
||||
<E t-if="state.flag" />
|
||||
<F t-else="!state.flag" />
|
||||
</div>`
|
||||
);
|
||||
class C extends TestWidget {
|
||||
@@ -2102,7 +2117,7 @@ describe("async rendering", () => {
|
||||
let n = 0;
|
||||
env.qweb.addTemplate(
|
||||
"W",
|
||||
`<div><t t-if="state.val > 1"><t t-widget="Child" val="state.val"/></t></div>`
|
||||
`<div><t t-if="state.val > 1"><Child val="state.val"/></t></div>`
|
||||
);
|
||||
class W extends Widget {
|
||||
widgets = { Child };
|
||||
@@ -2156,8 +2171,8 @@ describe("async rendering", () => {
|
||||
"Parent",
|
||||
`
|
||||
<div>
|
||||
<t t-if="state.flagA"><t t-widget="ChildA"/></t>
|
||||
<t t-if="state.flagB"><t t-widget="ChildB"/></t>
|
||||
<t t-if="state.flagA"><ChildA /></t>
|
||||
<t t-if="state.flagB"><ChildB /></t>
|
||||
</div>`
|
||||
);
|
||||
class Parent extends Widget {
|
||||
@@ -2203,8 +2218,8 @@ describe("async rendering", () => {
|
||||
"Parent",
|
||||
`
|
||||
<div>
|
||||
<t t-widget="ChildA" val="state.valA"/>
|
||||
<t t-if="state.flagB"><t t-widget="ChildB" val="state.valB"/></t>
|
||||
<ChildA val="state.valA"/>
|
||||
<t t-if="state.flagB"><ChildB val="state.valB"/></t>
|
||||
</div>`
|
||||
);
|
||||
class Parent extends Widget {
|
||||
@@ -2254,7 +2269,7 @@ describe("async rendering", () => {
|
||||
<ul>
|
||||
<t t-foreach="items" t-as="item">
|
||||
<li t-key="'li_'+item">
|
||||
<t t-widget="Child" item="item"/>
|
||||
<Child item="item"/>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
@@ -2271,7 +2286,7 @@ describe("async rendering", () => {
|
||||
test("properly behave when destroyed/unmounted while rendering ", async () => {
|
||||
let def = Promise.resolve();
|
||||
|
||||
env.qweb.addTemplate("Child", `<div><t t-widget="SubChild"/></div>`);
|
||||
env.qweb.addTemplate("Child", `<div><SubChild /></div>`);
|
||||
class Child extends Widget {
|
||||
widgets = { SubChild };
|
||||
mounted() {
|
||||
@@ -2298,7 +2313,7 @@ describe("async rendering", () => {
|
||||
env.qweb.addTemplate(
|
||||
"Parent",
|
||||
`
|
||||
<div><t t-if="state.flag"><t t-widget="Child" val="state.val"/></t></div>`
|
||||
<div><t t-if="state.flag"><Child val="state.val"/></t></div>`
|
||||
);
|
||||
class Parent extends Widget {
|
||||
widgets = { Child };
|
||||
@@ -2331,8 +2346,8 @@ describe("async rendering", () => {
|
||||
<span t-name="ChildB">b<t t-esc="props.val"/></span>
|
||||
<span t-name="Parent">
|
||||
<t t-if="state.flag">
|
||||
<t t-widget="ChildA" val="state.valA"/>
|
||||
<t t-widget="ChildB" val="state.valB"/>
|
||||
<ChildA val="state.valA"/>
|
||||
<ChildB val="state.valB"/>
|
||||
</t>
|
||||
</span>
|
||||
</templates>
|
||||
@@ -2368,14 +2383,14 @@ describe("async rendering", () => {
|
||||
expect(destroyCount).toBe(0);
|
||||
});
|
||||
|
||||
test("delayed t-widget with t-asyncroot directive", async () => {
|
||||
test("delayed component with t-asyncroot directive", async () => {
|
||||
env.qweb.addTemplates(`
|
||||
<templates>
|
||||
<div t-name="Parent">
|
||||
<button t-on-click="updateApp">Update App State</button>
|
||||
<div class="children">
|
||||
<t t-widget="Child" val="state.val"/>
|
||||
<t t-widget="AsyncChild" t-asyncroot="1" val="state.val"/>
|
||||
<Child val="state.val"/>
|
||||
<AsyncChild t-asyncroot="1" val="state.val"/>
|
||||
</div>
|
||||
</div>
|
||||
<span t-name="Child"><t t-esc="props.val"/></span>
|
||||
@@ -2423,14 +2438,14 @@ describe("async rendering", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("fast t-widget with t-asyncroot directive", async () => {
|
||||
test("fast component with t-asyncroot directive", async () => {
|
||||
env.qweb.addTemplates(`
|
||||
<templates>
|
||||
<div t-name="Parent">
|
||||
<button t-on-click="updateApp">Update App State</button>
|
||||
<div class="children">
|
||||
<t t-widget="Child" t-asyncroot="1" val="state.val"/>
|
||||
<t t-widget="AsyncChild" val="state.val"/>
|
||||
<Child t-asyncroot="1" val="state.val"/>
|
||||
<AsyncChild val="state.val"/>
|
||||
</div>
|
||||
</div>
|
||||
<span t-name="Child"><t t-esc="props.val"/></span>
|
||||
@@ -2484,8 +2499,8 @@ describe("async rendering", () => {
|
||||
<div t-name="Parent">
|
||||
<button t-on-click="updateApp">Update App State</button>
|
||||
<div class="children">
|
||||
<t t-widget="Child" val="state.val"/>
|
||||
<t t-widget="AsyncChild" t-asyncroot="1" val="state.val"/>
|
||||
<Child val="state.val"/>
|
||||
<AsyncChild t-asyncroot="1" val="state.val"/>
|
||||
</div>
|
||||
</div>
|
||||
<span t-name="Child" t-on-click="increment">
|
||||
@@ -2617,9 +2632,9 @@ describe("updating environment", () => {
|
||||
});
|
||||
|
||||
test("updating parent env does modify child env, part 2", async () => {
|
||||
env.qweb.addTemplate("ParentWidget", `<div><t t-widget="child"/></div>`);
|
||||
env.qweb.addTemplate("ParentWidget", `<div><Child/></div>`);
|
||||
class ParentWidget extends Widget {
|
||||
widgets = { child: Widget };
|
||||
widgets = { Child: Widget };
|
||||
}
|
||||
const parent = new ParentWidget(env);
|
||||
await parent.mount(fixture);
|
||||
@@ -2642,7 +2657,7 @@ describe("updating environment", () => {
|
||||
});
|
||||
|
||||
test("updating env force rerendering children", async () => {
|
||||
env.qweb.addTemplate("Parent", `<div><t t-widget="Child"/></div>`);
|
||||
env.qweb.addTemplate("Parent", `<div><Child /></div>`);
|
||||
class Parent extends Widget {
|
||||
widgets = { Child };
|
||||
}
|
||||
@@ -2680,7 +2695,7 @@ describe("widget and observable state", () => {
|
||||
expect.assertions(1);
|
||||
env.qweb.addTemplate(
|
||||
"Parent",
|
||||
`<div><t t-widget="Child" obj="state.obj"/></div>`
|
||||
`<div><Child obj="state.obj"/></div>`
|
||||
);
|
||||
class Parent extends Widget {
|
||||
state = { obj: { coffee: 1 } };
|
||||
@@ -2822,10 +2837,10 @@ describe("t-slot directive", () => {
|
||||
env.qweb.addTemplates(`
|
||||
<templates>
|
||||
<div t-name="Parent">
|
||||
<t t-widget="Dialog">
|
||||
<Dialog>
|
||||
<t t-set="header"><span>header</span></t>
|
||||
<t t-set="footer"><span>footer</span></t>
|
||||
</t>
|
||||
</Dialog>
|
||||
</div>
|
||||
<div t-name="Dialog">
|
||||
<div><t t-slot="header"/></div>
|
||||
@@ -2852,9 +2867,9 @@ describe("t-slot directive", () => {
|
||||
<templates>
|
||||
<div t-name="Parent">
|
||||
<span class="counter"><t t-esc="state.val"/></span>
|
||||
<t t-widget="Dialog">
|
||||
<Dialog>
|
||||
<t t-set="footer"><button t-on-click="doSomething">do something</button></t>
|
||||
</t>
|
||||
</Dialog>
|
||||
</div>
|
||||
<span t-name="Dialog"><t t-slot="footer"/></span>
|
||||
</templates>
|
||||
@@ -2887,9 +2902,9 @@ describe("t-slot directive", () => {
|
||||
<templates>
|
||||
<div t-name="Parent">
|
||||
<span class="counter"><t t-esc="state.val"/></span>
|
||||
<t t-widget="Dialog">
|
||||
<Dialog>
|
||||
<t t-set="footer"><button t-ref="myButton" t-on-click="doSomething">do something</button></t>
|
||||
</t>
|
||||
</Dialog>
|
||||
</div>
|
||||
<span t-name="Dialog"><t t-slot="footer"/></span>
|
||||
</templates>
|
||||
@@ -3153,9 +3168,9 @@ describe("t-model directive", () => {
|
||||
env.qweb.addTemplates(`
|
||||
<templates>
|
||||
<div t-name="Parent">
|
||||
<t t-widget="Dialog">
|
||||
<Dialog>
|
||||
<span>sts rocks</span>
|
||||
</t>
|
||||
</Dialog>
|
||||
</div>
|
||||
<div t-name="Dialog"><t t-slot="default"/></div>
|
||||
</templates>
|
||||
|
||||
+11
-11
@@ -534,8 +534,8 @@ describe("connecting a component to store", () => {
|
||||
"App",
|
||||
`
|
||||
<div>
|
||||
<t t-foreach="props.todos" t-as="todo" t-key="todo">
|
||||
<t t-widget="Todo" msg="todo.msg"/>
|
||||
<t t-foreach="props.todos" t-as="todo" >
|
||||
<Todo msg="todo.msg" t-key="todo"/>
|
||||
</t>
|
||||
</div>`
|
||||
);
|
||||
@@ -624,8 +624,8 @@ describe("connecting a component to store", () => {
|
||||
env.qweb.addTemplates(`
|
||||
<templates>
|
||||
<div t-name="App">
|
||||
<t t-foreach="props.todos" t-as="todo" t-key="todo">
|
||||
<t t-widget="Todo" msg="todo.msg"/>
|
||||
<t t-foreach="props.todos" t-as="todo">
|
||||
<Todo msg="todo.msg" t-key="todo" />
|
||||
</t>
|
||||
</div>
|
||||
<span t-name="Todo"><t t-esc="props.msg"/></span>
|
||||
@@ -734,7 +734,7 @@ describe("connecting a component to store", () => {
|
||||
"TodoList",
|
||||
`<div>
|
||||
<t t-foreach="props.todos" t-as="todo">
|
||||
<t t-widget="ConnectedTodo" id="todo.id"/>
|
||||
<ConnectedTodo id="todo.id" t-key="todo.id"/>
|
||||
</t>
|
||||
</div>`
|
||||
);
|
||||
@@ -801,7 +801,7 @@ describe("connecting a component to store", () => {
|
||||
"TodoList",
|
||||
`<div>
|
||||
<t t-foreach="props.todos" t-as="todo">
|
||||
<t t-widget="ConnectedTodo" id="todo.id"/>
|
||||
<ConnectedTodo id="todo.id" t-key="todo.id"/>
|
||||
</t>
|
||||
</div>`
|
||||
);
|
||||
@@ -839,7 +839,7 @@ describe("connecting a component to store", () => {
|
||||
env.qweb.addTemplate(
|
||||
"App",
|
||||
`<div>
|
||||
<t t-widget="ConnectedBeer" id="state.beerId"/>
|
||||
<ConnectedBeer id="state.beerId"/>
|
||||
</div>`
|
||||
);
|
||||
class App extends Component<any, any, any> {
|
||||
@@ -923,8 +923,8 @@ describe("connecting a component to store", () => {
|
||||
env.qweb.addTemplate(
|
||||
"App",
|
||||
`<div>
|
||||
<t t-widget="ConnectedBeer" id="state.beerId"/>
|
||||
</div>`
|
||||
<ConnectedBeer id="state.beerId"/>
|
||||
</div>`
|
||||
);
|
||||
class App extends Component<any, any, any> {
|
||||
widgets = { ConnectedBeer };
|
||||
@@ -995,7 +995,7 @@ describe("connecting a component to store", () => {
|
||||
env.qweb.addTemplate(
|
||||
"App",
|
||||
`<div>
|
||||
<t t-widget="ConnectedBeer" id="state.beerId"/>
|
||||
<ConnectedBeer id="state.beerId"/>
|
||||
</div>`
|
||||
);
|
||||
class App extends Component<any, any, any> {
|
||||
@@ -1074,7 +1074,7 @@ describe("connecting a component to store", () => {
|
||||
"Parent",
|
||||
`
|
||||
<div>
|
||||
<t t-widget="Child" key="props.current"/>
|
||||
<Child key="props.current"/>
|
||||
</div>
|
||||
`
|
||||
);
|
||||
|
||||
+19
-19
@@ -26,8 +26,8 @@ const COMPONENTS_XML = `<templates>
|
||||
</button>
|
||||
|
||||
<div t-name="App">
|
||||
<t t-widget="Counter"/>
|
||||
<t t-widget="Counter"/>
|
||||
<Counter />
|
||||
<Counter />
|
||||
</div>
|
||||
</templates>`;
|
||||
|
||||
@@ -88,7 +88,7 @@ const ANIMATION_XML = `<templates>
|
||||
<div class="demo">
|
||||
<button t-on-click="toggle('widgetFlag')">Toggle widget</button>
|
||||
<div>
|
||||
<t t-widget="Counter" t-if="state.widgetFlag" t-transition="fade"/>
|
||||
<Counter t-if="state.widgetFlag" t-transition="fade"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -98,7 +98,7 @@ const ANIMATION_XML = `<templates>
|
||||
<button t-on-click="addNumber">Add a number</button>
|
||||
<div>
|
||||
<t t-foreach="state.numbers" t-as="n">
|
||||
<span t-transition="fade" class="numberspan"><t t-esc="n"/></span>
|
||||
<span t-transition="fade" class="numberspan" t-key="n"><t t-esc="n"/></span>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
@@ -236,7 +236,7 @@ const LIFECYCLE_DEMO_XML = `<templates>
|
||||
<button t-on-click="increment">Increment Parent State</button>
|
||||
<button t-on-click="toggleSubWidget">Toggle SubWidget</button>
|
||||
<div t-if="state.flag">
|
||||
<t t-widget="DemoWidget" n="state.n"/>
|
||||
<DemoWidget n="state.n"/>
|
||||
</div>
|
||||
</div>
|
||||
</templates>`;
|
||||
@@ -483,7 +483,7 @@ const TODO_APP_STORE_XML = `<templates>
|
||||
<label for="toggle-all"></label>
|
||||
<ul class="todo-list">
|
||||
<t t-foreach="visibleTodos" t-as="todo">
|
||||
<t t-widget="TodoItem" t-key="todo.id" id="todo.id" completed="todo.completed" title="todo.title"/>
|
||||
<TodoItem t-key="todo.id" id="todo.id" completed="todo.completed" title="todo.title"/>
|
||||
</t>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -995,17 +995,17 @@ const RESPONSIVE_XML = `<templates>
|
||||
</div>
|
||||
|
||||
<div t-name="App" class="app" t-att-class="{mobile: env.isMobile, desktop: !env.isMobile}">
|
||||
<t t-widget="Navbar"/>
|
||||
<t t-widget="ControlPanel"/>
|
||||
<Navbar/>
|
||||
<ControlPanel/>
|
||||
<div class="content-wrapper" t-if="!env.isMobile">
|
||||
<div class="content">
|
||||
<t t-widget="FormView"/>
|
||||
<t t-widget="Chatter"/>
|
||||
<FormView />
|
||||
<Chatter />
|
||||
</div>
|
||||
</div>
|
||||
<t t-else="1">
|
||||
<t t-widget="FormView"/>
|
||||
<t t-widget="Chatter"/>
|
||||
<FormView />
|
||||
<Chatter />
|
||||
</t>
|
||||
</div>
|
||||
</templates>
|
||||
@@ -1128,17 +1128,17 @@ const SLOTS_XML = `<templates>
|
||||
</div>
|
||||
|
||||
<div t-name="App" class="main">
|
||||
<t t-widget="Card" title="'Title card A'">
|
||||
<Card title="'Title card A'">
|
||||
<t t-set="content">Content of card 1... [<t t-esc="state.a"/>]</t>
|
||||
<t t-set="footer"><button t-on-click="inc('a', 1)">Increment A</button></t>
|
||||
</t>
|
||||
<t t-widget="Card" title="'Title card B'">
|
||||
</Card>
|
||||
<Card title="'Title card B'">
|
||||
<div t-set="content">
|
||||
<div>Card 2... [<t t-esc="state.b"/>]</div>
|
||||
<t t-widget="Counter"/>
|
||||
<Counter />
|
||||
</div>
|
||||
<t t-set="footer"><button t-on-click="inc('b', -1)">Decrement B</button></t>
|
||||
</t>
|
||||
</Card>
|
||||
</div>
|
||||
</templates>`;
|
||||
|
||||
@@ -1226,8 +1226,8 @@ app.mount(document.body);
|
||||
const ASYNC_COMPONENTS_XML = `<templates>
|
||||
<div t-name="App" class="app">
|
||||
<button t-on-click="increment">Increment</button>
|
||||
<t t-widget="SlowWidget" value="state.value"/>
|
||||
<t t-widget="NotificationList" t-asyncroot="1" notifications="state.notifs"/>
|
||||
<SlowWidget value="state.value"/>
|
||||
<NotificationList t-asyncroot="1" notifications="state.notifs"/>
|
||||
</div>
|
||||
|
||||
<div t-name="SlowWidget" class="value" >
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
<a class="btn flash" t-on-click="downloadCode" title="Download a Zip with this Code"><i class="fas fa-download"></i></a>
|
||||
<a class="layout-selector flash" t-on-click="toggleLayout" title="Toggle Layout"><i class="fas" t-att-class="state.splitLayout ? 'fa-toggle-on' : 'fa-toggle-off'"></i></a>
|
||||
</div>
|
||||
<t t-widget="TabbedEditor"
|
||||
<TabbedEditor
|
||||
js="state.js"
|
||||
css="!state.splitLayout and state.css"
|
||||
xml="!state.splitLayout and state.js"
|
||||
t-att-style="topEditorStyle"/>
|
||||
<t t-if="state.splitLayout">
|
||||
<div class="separator horizontal"/>
|
||||
<t t-widget="TabbedEditor" t-keepalive="1"
|
||||
<TabbedEditor t-keepalive="1"
|
||||
js="false"
|
||||
css="state.css"
|
||||
xml="state.xml"
|
||||
|
||||
Reference in New Issue
Block a user