[IMP] component: components key is now static

This is a breaking change!

closes #279
This commit is contained in:
Géry Debongnie
2019-09-10 22:37:08 +02:00
parent 2a40907e35
commit e1acf66143
16 changed files with 548 additions and 530 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ class Counter extends owl.Component {
}
class App extends owl.Component {
components = { Counter };
static components = { Counter };
}
const qweb = new owl.QWeb(TEMPLATES);
+15 -5
View File
@@ -113,6 +113,16 @@ find a template with the component name (or one of its ancestor).
### Static Properties
- **`components`** (Object, optional): if given, this is an object that contains
the classes of any sub components needed by the template. This is the main way
used by Owl to be able to create sub components.
```js
class ParentComponent extends owl.Component {
static components = { SubComponent };
}
```
- **`props`** (Object, optional): if given, this is an object that describes the
type and shape of the (actual) props given to the component. If Owl mode is
`dev`, this will be used to validate the props each time the component is
@@ -420,7 +430,7 @@ to be capitalized.
```js
class ParentComponent extends owl.Component {
components = { MyComponent: MyComponent};
static components = { MyComponent: MyComponent};
...
}
```
@@ -442,16 +452,16 @@ that the template can access `state`, `props`, `env`, or any methods defined in
```js
class ParentComponent {
components = { ChildComponent };
static components = { ChildComponent };
state = { val: 4 };
}
```
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
actual component class in the special static `components` key, or the class registered in
QWeb's global registry (see `register` function of QWeb). It first looks inside
the local `components` key, then fallbacks on the global registry.
the static `components` key, then fallbacks on the global registry.
_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
@@ -471,7 +481,7 @@ The `t-component` directive can also be used to accept dynamic values with strin
```js
class ParentComponent {
components = { ChildComponent1, ChildComponent2 };
static components = { ChildComponent1, ChildComponent2 };
state = { id: 1 };
}
```
+1
View File
@@ -92,6 +92,7 @@ export class Component<T extends Env, Props extends {}, State extends {}> {
get el(): HTMLElement | null {
return this.__owl__.vnode ? (<any>this).__owl__.vnode.elm : null;
}
static components = {};
env: T;
state?: State;
+1 -1
View File
@@ -388,7 +388,7 @@ QWeb.addDirective({
// new component
ctx.addLine(`let componentKey${componentID} = ${ctx.interpolate(value)};`);
ctx.addLine(
`let W${componentID} = context.components && context.components[componentKey${componentID}] || QWeb.components[componentKey${componentID}];`
`let W${componentID} = context.constructor.components[componentKey${componentID}] || QWeb.components[componentKey${componentID}];`
);
// maybe only do this in dev mode...
ctx.addLine(
+2 -2
View File
@@ -26,7 +26,7 @@ exports[`animations t-transition combined with component 1`] = `
}
if (!w4) {
let componentKey4 = \`Child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -71,7 +71,7 @@ exports[`animations t-transition combined with t-component and t-if 1`] = `
}
if (!w4) {
let componentKey4 = \`Child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
+6 -6
View File
@@ -175,10 +175,10 @@ describe("animations", () => {
env.qweb.addTemplate("Parent", `<div><Child t-transition="chimay"/></div>`);
env.qweb.addTemplate("Child", `<span>blue</span>`);
class Parent extends Widget {
components = { Child: Child };
}
class Child extends Widget {}
class Parent extends Widget {
static components = { Child: Child };
}
const widget = new Parent(env);
let def = makeDeferred();
@@ -214,11 +214,11 @@ describe("animations", () => {
`<div><t t-if="state.display" t-component="Child" t-transition="chimay"/></div>`
);
env.qweb.addTemplate("Child", `<span>blue</span>`);
class Child extends Widget {}
class Parent extends Widget {
components = { Child: Child };
static components = { Child: Child };
state = { display: true };
}
class Child extends Widget {}
const widget = new Parent(env);
let def = makeDeferred();
@@ -356,7 +356,7 @@ describe("animations", () => {
);
class Child extends Widget {}
class Parent extends Widget {
components = { Child };
static components = { Child };
constructor(parent) {
super(parent);
this.state = { flag: false };
@@ -39,7 +39,7 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = `
}
if (!w8) {
let componentKey8 = \`Child\`;
let W8 = context.components && context.components[componentKey8] || QWeb.components[componentKey8];
let W8 = context.constructor.components[componentKey8] || QWeb.components[componentKey8];
if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')}
w8 = new W8(parent, props8);
parent.__owl__.cmap[8] = w8.__owl__.id;
@@ -67,7 +67,7 @@ exports[`async rendering delayed component with t-asyncroot directive 1`] = `
}
if (!w11) {
let componentKey11 = \`AsyncChild\`;
let W11 = context.components && context.components[componentKey11] || QWeb.components[componentKey11];
let W11 = context.constructor.components[componentKey11] || QWeb.components[componentKey11];
if (!W11) {throw new Error('Cannot find the definition of component \\"' + componentKey11 + '\\"')}
w11 = new W11(parent, props11);
parent.__owl__.cmap[11] = w11.__owl__.id;
@@ -122,7 +122,7 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = `
}
if (!w8) {
let componentKey8 = \`Child\`;
let W8 = context.components && context.components[componentKey8] || QWeb.components[componentKey8];
let W8 = context.constructor.components[componentKey8] || QWeb.components[componentKey8];
if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')}
w8 = new W8(parent, props8);
parent.__owl__.cmap[8] = w8.__owl__.id;
@@ -149,7 +149,7 @@ exports[`async rendering fast component with t-asyncroot directive 1`] = `
}
if (!w11) {
let componentKey11 = \`AsyncChild\`;
let W11 = context.components && context.components[componentKey11] || QWeb.components[componentKey11];
let W11 = context.constructor.components[componentKey11] || QWeb.components[componentKey11];
if (!W11) {throw new Error('Cannot find the definition of component \\"' + componentKey11 + '\\"')}
w11 = new W11(parent, props11);
parent.__owl__.cmap[11] = w11.__owl__.id;
@@ -203,7 +203,7 @@ exports[`async rendering t-component with t-asyncroot directive: mixed re-render
}
if (!w8) {
let componentKey8 = \`Child\`;
let W8 = context.components && context.components[componentKey8] || QWeb.components[componentKey8];
let W8 = context.constructor.components[componentKey8] || QWeb.components[componentKey8];
if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')}
w8 = new W8(parent, props8);
parent.__owl__.cmap[8] = w8.__owl__.id;
@@ -231,7 +231,7 @@ exports[`async rendering t-component with t-asyncroot directive: mixed re-render
}
if (!w11) {
let componentKey11 = \`AsyncChild\`;
let W11 = context.components && context.components[componentKey11] || QWeb.components[componentKey11];
let W11 = context.constructor.components[componentKey11] || QWeb.components[componentKey11];
if (!W11) {throw new Error('Cannot find the definition of component \\"' + componentKey11 + '\\"')}
w11 = new W11(parent, props11);
parent.__owl__.cmap[11] = w11.__owl__.id;
@@ -273,7 +273,7 @@ exports[`class and style attributes with t-component dynamic t-att-style is prop
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -317,7 +317,7 @@ exports[`class and style attributes with t-component t-att-class is properly add
}
if (!w4) {
let componentKey4 = \`Child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -375,7 +375,7 @@ exports[`class and style attributes with t-component t-att-class is properly add
}
if (!w4) {
let componentKey4 = \`Child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -431,7 +431,7 @@ exports[`class and style attributes with t-component t-att-class is properly add
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -474,7 +474,7 @@ exports[`composition sub components dom state with t-keepalive is preserved 1`]
}
if (!w4) {
let componentKey4 = \`InputWidget\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -533,7 +533,7 @@ exports[`composition sub components with some state rendered in a loop 1`] = `
}
if (!w7) {
let componentKey7 = \`ChildWidget\`;
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
let W7 = context.constructor.components[componentKey7] || QWeb.components[componentKey7];
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
w7 = new W7(parent, props7);
parent.__owl__.cmap[templateId9] = w7.__owl__.id;
@@ -575,7 +575,7 @@ exports[`composition t-component with dynamic value 1`] = `
}
if (!w4) {
let componentKey4 = (context['state'].widget);
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -616,7 +616,7 @@ exports[`composition t-component with dynamic value 2 1`] = `
}
if (!w4) {
let componentKey4 = \`Widget\${context['state'].widget}\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -658,7 +658,7 @@ exports[`lifecycle hooks willPatch/patched hook with t-keepalive 1`] = `
}
if (!w4) {
let componentKey4 = \`ChildWidget\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -700,7 +700,7 @@ exports[`other directives with t-component t-on with handler bound to argument 1
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -741,7 +741,7 @@ exports[`other directives with t-component t-on with handler bound to empty obje
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -782,7 +782,7 @@ exports[`other directives with t-component t-on with handler bound to empty obje
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -823,7 +823,7 @@ exports[`other directives with t-component t-on with handler bound to object 1`]
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -864,7 +864,7 @@ exports[`other directives with t-component t-on with prevent and self modifiers
}
if (!w4) {
let componentKey4 = \`Child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -905,7 +905,7 @@ exports[`other directives with t-component t-on with self and prevent modifiers
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -946,7 +946,7 @@ exports[`other directives with t-component t-on with self modifier 1`] = `
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -987,7 +987,7 @@ exports[`other directives with t-component t-on with stop and/or prevent modifie
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -1030,7 +1030,7 @@ exports[`random stuff/miscellaneous snapshotting compiled code 1`] = `
}
if (!w4) {
let componentKey4 = \`child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[templateId6] = w4.__owl__.id;
@@ -1089,7 +1089,7 @@ exports[`random stuff/miscellaneous t-on with handler bound to dynamic argument
}
if (!w7) {
let componentKey7 = \`Child\`;
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
let W7 = context.constructor.components[componentKey7] || QWeb.components[componentKey7];
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
w7 = new W7(parent, props7);
parent.__owl__.cmap[templateId9] = w7.__owl__.id;
@@ -1306,7 +1306,7 @@ exports[`t-slot directive can define and call slots 1`] = `
}
if (!w4) {
let componentKey4 = \`Dialog\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -1545,7 +1545,7 @@ exports[`t-slot directive slots are rendered with proper context, part 2 2`] = `
}
if (!w9) {
let componentKey9 = \`Link\`;
let W9 = context.components && context.components[componentKey9] || QWeb.components[componentKey9];
let W9 = context.constructor.components[componentKey9] || QWeb.components[componentKey9];
if (!W9) {throw new Error('Cannot find the definition of component \\"' + componentKey9 + '\\"')}
w9 = new W9(parent, props9);
parent.__owl__.cmap[templateId10] = w9.__owl__.id;
@@ -1648,7 +1648,7 @@ exports[`t-slot directive slots are rendered with proper context, part 3 2`] = `
}
if (!w10) {
let componentKey10 = \`Link\`;
let W10 = context.components && context.components[componentKey10] || QWeb.components[componentKey10];
let W10 = context.constructor.components[componentKey10] || QWeb.components[componentKey10];
if (!W10) {throw new Error('Cannot find the definition of component \\"' + componentKey10 + '\\"')}
w10 = new W10(parent, props10);
parent.__owl__.cmap[templateId11] = w10.__owl__.id;
@@ -1705,7 +1705,7 @@ exports[`t-slot directive slots are rendered with proper context, part 4 1`] = `
}
if (!w5) {
let componentKey5 = \`Link\`;
let W5 = context.components && context.components[componentKey5] || QWeb.components[componentKey5];
let W5 = context.constructor.components[componentKey5] || QWeb.components[componentKey5];
if (!W5) {throw new Error('Cannot find the definition of component \\"' + componentKey5 + '\\"')}
w5 = new W5(parent, props5);
parent.__owl__.cmap[5] = w5.__owl__.id;
@@ -1759,7 +1759,7 @@ exports[`top level sub widgets basic use 1`] = `
}
if (!w3) {
let componentKey3 = \`Child\`;
let W3 = context.components && context.components[componentKey3] || QWeb.components[componentKey3];
let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3];
if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')}
w3 = new W3(parent, props3);
parent.__owl__.cmap[3] = w3.__owl__.id;
@@ -1800,7 +1800,7 @@ exports[`top level sub widgets can select a sub widget 1`] = `
}
if (!w3) {
let componentKey3 = \`Child\`;
let W3 = context.components && context.components[componentKey3] || QWeb.components[componentKey3];
let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3];
if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')}
w3 = new W3(parent, props3);
parent.__owl__.cmap[3] = w3.__owl__.id;
@@ -1829,7 +1829,7 @@ exports[`top level sub widgets can select a sub widget 1`] = `
}
if (!w7) {
let componentKey7 = \`OtherChild\`;
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
let W7 = context.constructor.components[componentKey7] || QWeb.components[componentKey7];
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
w7 = new W7(parent, props7);
parent.__owl__.cmap[7] = w7.__owl__.id;
@@ -30,7 +30,7 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] =
}
if (!w4) {
let componentKey4 = \`Child\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
utils.validateProps(W4, props4)
w4 = new W4(parent, props4);
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -235,7 +235,7 @@ describe("props validation", () => {
static props = ["message"];
}
class App extends Widget {
components = { Child };
static components = { Child };
}
const app = new App(env);
await app.mount(fixture);
+2 -2
View File
@@ -31,7 +31,7 @@ describe("Link component", () => {
</templates>
`);
class App extends Component<any, any, any> {
components = { Link: Link };
static components = { Link: Link };
}
const routes = [{ name: "about", path: "/about" }, { name: "users", path: "/users" }];
@@ -62,7 +62,7 @@ describe("Link component", () => {
</templates>
`);
class App extends Component<any, any, any> {
components = { Link: Link };
static components = { Link: Link };
}
const routes = [{ name: "about", path: "/about" }, { name: "users", path: "/users" }];
@@ -27,7 +27,7 @@ exports[`router directive t-routecomponent can render parameterized route 1`] =
}
if (!w4) {
let componentKey4 = \`__component__book\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -70,7 +70,7 @@ exports[`router directive t-routecomponent can render parameterized route with s
}
if (!w4) {
let componentKey4 = \`__component__book\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -113,7 +113,7 @@ exports[`router directive t-routecomponent can render simple cases 1`] = `
}
if (!w4) {
let componentKey4 = \`__component__about\`;
let W4 = context.components && context.components[componentKey4] || QWeb.components[componentKey4];
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4];
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
w4 = new W4(parent, props4);
parent.__owl__.cmap[4] = w4.__owl__.id;
@@ -142,7 +142,7 @@ exports[`router directive t-routecomponent can render simple cases 1`] = `
}
if (!w7) {
let componentKey7 = \`__component__users\`;
let W7 = context.components && context.components[componentKey7] || QWeb.components[componentKey7];
let W7 = context.constructor.components[componentKey7] || QWeb.components[componentKey7];
if (!W7) {throw new Error('Cannot find the definition of component \\"' + componentKey7 + '\\"')}
w7 = new W7(parent, props7);
parent.__owl__.cmap[7] = w7.__owl__.id;
+48 -48
View File
@@ -27,13 +27,13 @@ describe("connecting a component to store", () => {
<span t-name="Todo"><t t-esc="props.msg"/></span>
</templates>
`);
class Todo extends Component<any, any, any> {}
class App extends ConnectedComponent<any, any, any> {
components = { Todo };
static components = { Todo };
static mapStoreToProps(s) {
return { todos: s.todos };
}
}
class Todo extends Component<any, any, any> {}
const state = { todos: [] };
const actions = {
addTodo({ state }, msg) {
@@ -122,7 +122,7 @@ describe("connecting a component to store", () => {
}
});
class App extends ConnectedComponent<any, any, any> {
components = { Todo };
static components = { Todo };
static mapStoreToProps(s) {
return { todos: s.todos };
}
@@ -200,7 +200,7 @@ describe("connecting a component to store", () => {
}
class Parent extends Component<any, any, any> {
components = { Child };
static components = { Child };
constructor(env: Env) {
super(env);
@@ -248,7 +248,7 @@ describe("connecting a component to store", () => {
}
class TodoList extends ConnectedComponent<any, any, any> {
components = { TodoItem };
static components = { TodoItem };
static mapStoreToProps(state) {
return { todos: state.todos };
}
@@ -305,7 +305,7 @@ describe("connecting a component to store", () => {
}
class TodoList extends ConnectedComponent<any, any, any> {
components = { TodoItem };
static components = { TodoItem };
static mapStoreToProps(state) {
return { todos: state.todos };
}
@@ -337,7 +337,7 @@ describe("connecting a component to store", () => {
}
class App extends Component<any, any, any> {
components = { Beer };
static components = { Beer };
state = { beerId: 1 };
}
@@ -414,7 +414,7 @@ describe("connecting a component to store", () => {
}
class App extends Component<any, any, any> {
components = { Beer };
static components = { Beer };
state = { beerId: 0 };
}
@@ -481,7 +481,7 @@ describe("connecting a component to store", () => {
}
class App extends Component<any, any, any> {
components = { Beer };
static components = { Beer };
state = { beerId: 0 };
}
@@ -559,20 +559,20 @@ describe("connecting a component to store", () => {
</templates>
`);
class Parent extends ConnectedComponent<any, any, any> {
components = { Child };
static mapStoreToProps(s) {
steps.push("parent");
return { current: s.current, isvisible: s.isvisible };
}
}
class Child extends ConnectedComponent<any, any, any> {
static mapStoreToProps(s, props) {
steps.push("child");
return { msg: s.msg[props.key] };
}
}
class Parent extends ConnectedComponent<any, any, any> {
static components = { Child };
static mapStoreToProps(s) {
steps.push("parent");
return { current: s.current, isvisible: s.isvisible };
}
}
const state = { current: "a", msg: { a: "a", b: "b" } };
const actions = {
@@ -609,8 +609,14 @@ describe("connecting a component to store", () => {
</templates>
`);
class Child extends ConnectedComponent<any, any, any> {
static mapStoreToProps(s, props) {
steps.push("child");
return { msg: s.messages[props.someId] };
}
}
class Parent extends ConnectedComponent<any, any, any> {
components = { Child };
static components = { Child };
static mapStoreToProps(s) {
steps.push("parent");
return { flag: s.flag, someId: s.someId };
@@ -621,12 +627,6 @@ describe("connecting a component to store", () => {
}
}
class Child extends ConnectedComponent<any, any, any> {
static mapStoreToProps(s, props) {
steps.push("child");
return { msg: s.messages[props.someId] };
}
}
const state = { someId: 1, flag: true, messages: { 1: "abc" } };
const actions = {
@@ -685,15 +685,6 @@ describe("connecting a component to store", () => {
</templates>
`);
class TodoApp extends ConnectedComponent<any, any, any> {
components = { TodoItem };
static mapStoreToProps(state) {
return {
todos: state.todos
};
}
}
let renderCount = 0;
let fCount = 0;
@@ -714,6 +705,15 @@ describe("connecting a component to store", () => {
return super.__render(...args);
}
}
class TodoApp extends ConnectedComponent<any, any, any> {
static components = { TodoItem };
static mapStoreToProps(state) {
return {
todos: state.todos
};
}
}
(<any>env).store = store;
const app = new TodoApp(env);
@@ -764,15 +764,6 @@ describe("connecting a component to store", () => {
</templates>
`);
class TodoApp extends ConnectedComponent<any, any, any> {
components = { TodoItem };
static mapStoreToProps(state) {
return {
todos: state.todos
};
}
}
let renderCount = 0;
let fCount = 0;
@@ -794,6 +785,15 @@ describe("connecting a component to store", () => {
}
}
class TodoApp extends ConnectedComponent<any, any, any> {
static components = { TodoItem };
static mapStoreToProps(state) {
return {
todos: state.todos
};
}
}
(<any>env).store = store;
const app = new TodoApp(env);
@@ -879,7 +879,7 @@ describe("connected components and default values", () => {
}
class App extends Component<any, any, any> {
components = { Greeter };
static components = { Greeter };
}
const store = new Store({ state: {} });
@@ -903,7 +903,7 @@ describe("connected components and default values", () => {
}
class App extends Component<any, any, any> {
components = { Greeter };
static components = { Greeter };
}
const store = new Store({ state: {} });
@@ -948,7 +948,7 @@ describe("connected components and default values", () => {
}
class Thread extends ConnectedComponent<any, any, any> {
components = { Message };
static components = { Message };
static defaultProps = { showMessages: true };
static mapStoreToProps = function(state, ownProps) {
const thread = state.threads[ownProps.threadId];
@@ -959,7 +959,7 @@ describe("connected components and default values", () => {
}
class App extends Component<any, any, any> {
components = { Thread };
static components = { Thread };
static defaultProps = { threadId: 1 };
}
@@ -1026,7 +1026,7 @@ describe("connected components and default values", () => {
}
class Parent extends Component<any, any, any> {
components = { Child };
static components = { Child };
state = { child: true };
}
@@ -1157,7 +1157,7 @@ describe("various scenarios", () => {
attachmentIds: state.messages[10].attachmentIds
};
}
components = { Attachment };
static components = { Attachment };
state = { isAttachmentDeleted: false };
doStuff() {
this.dispatch("deleteAttachment", 100);
+2 -2
View File
@@ -15,7 +15,7 @@ class Counter extends owl.Component {
// Message Widget
//------------------------------------------------------------------------------
class Message extends owl.Component {
components = { Counter };
static components = { Counter };
shouldUpdate(nextProps) {
return nextProps.message !== this.props.message;
@@ -31,7 +31,7 @@ class Message extends owl.Component {
// Root Widget
//------------------------------------------------------------------------------
class App extends owl.Component {
components = { Message };
static components = { Message };
state = { messages: [], multipleFlag: false, clearAfterFlag: false };
mounted() {
+92 -91
View File
@@ -150,6 +150,97 @@ Promise.all([loadTemplates(), owl.utils.whenReady()]).then(start);
return zip.generateAsync({ type: "blob" });
}
//------------------------------------------------------------------------------
// Tabbed editor
//------------------------------------------------------------------------------
class TabbedEditor extends owl.Component {
constructor(parent, props) {
super(parent, props);
this.state = {
currentTab: props.js ? "js" : props.xml ? "xml" : "css"
};
this.setTab = owl.utils.debounce(this.setTab, 250, true);
this.sessions = {};
this._setupSessions(props);
this.editor = null;
}
mounted() {
this.editor = this.editor || ace.edit(this.refs.editor);
this.editor.setValue(this.props[this.state.currentTab], -1);
this.editor.setFontSize("12px");
this.editor.setTheme("ace/theme/monokai");
this.editor.setSession(this.sessions[this.state.currentTab]);
const tabSize = this.state.currentTab === "xml" ? 2 : 4;
this.editor.session.setOption("tabSize", tabSize);
this.editor.on("blur", () => {
const editorValue = this.editor.getValue();
const propsValue = this.props[this.state.currentTab];
if (editorValue !== propsValue) {
this.trigger("updateCode", {
type: this.state.currentTab,
value: editorValue
});
}
});
}
willUpdateProps(nextProps) {
this._setupSessions(nextProps);
}
patched() {
const session = this.sessions[this.state.currentTab];
let content = this.props[this.state.currentTab];
if (content === false) {
const tab = this.props.js ? "js" : this.props.xml ? "xml" : "css";
content = this.props[tab];
this.state.currentTab = tab;
}
session.setValue(content, -1);
this.editor.setSession(session);
this.editor.resize();
}
setTab(tab) {
if (this.state.currentTab !== tab) {
this.state.currentTab = tab;
const session = this.sessions[this.state.currentTab];
session.doc.setValue(this.props[tab], -1);
this.editor.setSession(session);
}
}
onMouseDown(ev) {
if (ev.target.tagName === "DIV") {
let y = ev.clientY;
const resizer = ev => {
const delta = ev.clientY - y;
y = ev.clientY;
this.trigger("updatePanelHeight", { delta });
};
document.body.addEventListener("mousemove", resizer);
document.body.addEventListener("mouseup", () => {
document.body.removeEventListener("mousemove", resizer);
});
}
}
_setupSessions(props) {
for (let tab of ["js", "xml", "css"]) {
if (props[tab] && !this.sessions[tab]) {
this.sessions[tab] = new ace.EditSession(props[tab], MODES[tab]);
this.sessions[tab].setOption("useWorker", false);
const tabSize = tab === "xml" ? 2 : 4;
this.sessions[tab].setOption("tabSize", tabSize);
this.sessions[tab].setUndoManager(new ace.UndoManager());
}
}
}
}
//------------------------------------------------------------------------------
// MAIN APP
//------------------------------------------------------------------------------
@@ -158,7 +249,6 @@ class App extends owl.Component {
super(...args);
this.version = owl.__info__.version;
this.SAMPLES = SAMPLES;
this.components = { TabbedEditor };
this.state = {
js: SAMPLES[0].code,
@@ -270,97 +360,8 @@ class App extends owl.Component {
saveAs(content, "app.zip");
}
}
App.components = { TabbedEditor };
//------------------------------------------------------------------------------
// Tabbed editor
//------------------------------------------------------------------------------
class TabbedEditor extends owl.Component {
constructor(parent, props) {
super(parent, props);
this.state = {
currentTab: props.js ? "js" : props.xml ? "xml" : "css"
};
this.setTab = owl.utils.debounce(this.setTab, 250, true);
this.sessions = {};
this._setupSessions(props);
this.editor = null;
}
mounted() {
this.editor = this.editor || ace.edit(this.refs.editor);
this.editor.setValue(this.props[this.state.currentTab], -1);
this.editor.setFontSize("12px");
this.editor.setTheme("ace/theme/monokai");
this.editor.setSession(this.sessions[this.state.currentTab]);
const tabSize = this.state.currentTab === "xml" ? 2 : 4;
this.editor.session.setOption("tabSize", tabSize);
this.editor.on("blur", () => {
const editorValue = this.editor.getValue();
const propsValue = this.props[this.state.currentTab];
if (editorValue !== propsValue) {
this.trigger("updateCode", {
type: this.state.currentTab,
value: editorValue
});
}
});
}
willUpdateProps(nextProps) {
this._setupSessions(nextProps);
}
patched() {
const session = this.sessions[this.state.currentTab];
let content = this.props[this.state.currentTab];
if (content === false) {
const tab = this.props.js ? "js" : this.props.xml ? "xml" : "css";
content = this.props[tab];
this.state.currentTab = tab;
}
session.setValue(content, -1);
this.editor.setSession(session);
this.editor.resize();
}
setTab(tab) {
if (this.state.currentTab !== tab) {
this.state.currentTab = tab;
const session = this.sessions[this.state.currentTab];
session.doc.setValue(this.props[tab], -1);
this.editor.setSession(session);
}
}
onMouseDown(ev) {
if (ev.target.tagName === "DIV") {
let y = ev.clientY;
const resizer = ev => {
const delta = ev.clientY - y;
y = ev.clientY;
this.trigger("updatePanelHeight", { delta });
};
document.body.addEventListener("mousemove", resizer);
document.body.addEventListener("mouseup", () => {
document.body.removeEventListener("mousemove", resizer);
});
}
}
_setupSessions(props) {
for (let tab of ["js", "xml", "css"]) {
if (props[tab] && !this.sessions[tab]) {
this.sessions[tab] = new ace.EditSession(props[tab], MODES[tab]);
this.sessions[tab].setOption("useWorker", false);
const tabSize = tab === "xml" ? 2 : 4;
this.sessions[tab].setOption("tabSize", tabSize);
this.sessions[tab].setUndoManager(new ace.UndoManager());
}
}
}
}
//------------------------------------------------------------------------------
// Application initialization
+28 -29
View File
@@ -10,7 +10,7 @@ class Greeter extends owl.Component {
// Main root component
class App extends owl.Component {
components = { Greeter };
static components = { Greeter };
state = { name: 'World'};
}
@@ -56,7 +56,7 @@ class Counter extends owl.Component {
class App extends owl.Component {
state = { flag: false, componentFlag: false, numbers: [] };
components = { Counter };
static components = { Counter };
toggle(key) {
this.state[key] = !this.state[key];
@@ -214,7 +214,7 @@ class DemoComponent extends owl.Component {
}
class App extends owl.Component {
components = { DemoComponent };
static components = { DemoComponent };
state = { n: 0, flag: true };
increment() {
@@ -388,7 +388,7 @@ class TodoItem extends owl.Component {
// TodoApp
//------------------------------------------------------------------------------
class TodoApp extends owl.store.ConnectedComponent {
components = { TodoItem };
static components = { TodoItem };
state = { filter: "all" };
static mapStoreToProps(state) {
@@ -896,25 +896,24 @@ 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 {
components = { MobileSearchView };
}
class MobileSearchView extends owl.Component {}
class FormView extends owl.Component {
components = { AdvancedComponent };
class ControlPanel extends owl.Component {
static components = { MobileSearchView };
}
class AdvancedComponent extends owl.Component {}
class FormView extends owl.Component {
static components = { AdvancedComponent };
}
class Chatter extends owl.Component {
messages = Array.from(Array(100).keys());
}
class MobileSearchView extends owl.Component {}
class App extends owl.Component {
components = { Navbar, ControlPanel, FormView, Chatter };
static components = { Navbar, ControlPanel, FormView, Chatter };
}
//------------------------------------------------------------------------------
@@ -1072,7 +1071,7 @@ class Counter extends owl.Component {
// Main root component
class App extends owl.Component {
components = {Card, Counter};
static components = {Card, Counter};
state = {a: 1, b: 3};
inc(key, delta) {
@@ -1170,8 +1169,18 @@ const ASYNC_COMPONENTS = `// This example will not work if your browser does not
// because of the slow component. We use the 't-asyncroot' directive for this
// purpose. Try removing it to see the difference.
class SlowComponent extends owl.Component {
willUpdateProps() {
// 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));
}
}
class NotificationList extends owl.Component {}
class App extends owl.Component {
components = {SlowComponent, NotificationList};
static components = {SlowComponent, NotificationList};
state = { value: 0, notifs: [] };
increment() {
@@ -1185,16 +1194,6 @@ class App extends owl.Component {
}
}
class SlowComponent extends owl.Component {
willUpdateProps() {
// 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));
}
}
class NotificationList extends owl.Component {}
const qweb = new owl.QWeb(TEMPLATES);
const app = new App({ qweb });
app.mount(document.body);
@@ -1368,7 +1367,7 @@ class Window extends owl.Component {
}
class WindowManager extends owl.Component {
components = { Window };
static components = { Window };
windows = [];
nextId = 1;
currentZindex = 1;
@@ -1384,12 +1383,12 @@ class WindowManager extends owl.Component {
left: 0,
zindex: this.currentZindex++
});
this.components[id] = info.component;
this.constructor.components[id] = info.component;
this.render();
}
closeWindow(ev) {
const id = ev.detail.id;
delete this.components[id];
delete this.constructor.components[id];
const index = this.windows.findIndex(w => w.id === id);
this.windows.splice(index, 1);
this.render();
@@ -1409,7 +1408,7 @@ class WindowManager extends owl.Component {
}
class App extends owl.Component {
components = { WindowManager };
static components = { WindowManager };
addWindow(name) {
this.refs.wm.addWindow(name);