mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
make widget class generic on props
This commit is contained in:
@@ -23,8 +23,8 @@ interface Meta<T extends WEnv> {
|
|||||||
isStarted: boolean;
|
isStarted: boolean;
|
||||||
isMounted: boolean;
|
isMounted: boolean;
|
||||||
isDestroyed: boolean;
|
isDestroyed: boolean;
|
||||||
parent: Widget<T> | null;
|
parent: Widget<T, {}> | null;
|
||||||
children: { [key: number]: Widget<T> };
|
children: { [key: number]: Widget<T, {}> };
|
||||||
// children mapping: from templateID to widgetID
|
// children mapping: from templateID to widgetID
|
||||||
// should it be a map number => Widget?
|
// should it be a map number => Widget?
|
||||||
cmap: { [key: number]: number };
|
cmap: { [key: number]: number };
|
||||||
@@ -35,7 +35,7 @@ const patch = init([sdListeners, sdAttrs]);
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Widget
|
// Widget
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
export class Widget<T extends WEnv> {
|
export class Widget<T extends WEnv, Props> {
|
||||||
__widget__: Meta<WEnv>;
|
__widget__: Meta<WEnv>;
|
||||||
name: string = "widget";
|
name: string = "widget";
|
||||||
template: string = "<div></div>";
|
template: string = "<div></div>";
|
||||||
@@ -46,18 +46,18 @@ export class Widget<T extends WEnv> {
|
|||||||
|
|
||||||
env: T;
|
env: T;
|
||||||
state: Object = {};
|
state: Object = {};
|
||||||
props: any;
|
props: Props | undefined;
|
||||||
refs: { [key: string]: Widget<T> | HTMLElement | undefined } = {};
|
refs: { [key: string]: Widget<T, {}> | HTMLElement | undefined } = {};
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
constructor(parent: Widget<T> | T, props?: any) {
|
constructor(parent: Widget<T, {}> | T, props?: Props) {
|
||||||
wl.push(this);
|
wl.push(this);
|
||||||
this.props = props;
|
this.props = props;
|
||||||
let id: number;
|
let id: number;
|
||||||
let p: Widget<T> | null = null;
|
let p: Widget<T, any> | null = null;
|
||||||
if (parent instanceof Widget) {
|
if (parent instanceof Widget) {
|
||||||
p = parent;
|
p = parent;
|
||||||
this.env = parent.env;
|
this.env = parent.env;
|
||||||
@@ -83,7 +83,7 @@ export class Widget<T extends WEnv> {
|
|||||||
|
|
||||||
mounted() {}
|
mounted() {}
|
||||||
|
|
||||||
shouldUpdate(nextProps: any): boolean {
|
shouldUpdate(nextProps: Props): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ export class Widget<T extends WEnv> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProps(nextProps?: any): Promise<void> {
|
updateProps(nextProps: Props): Promise<void> {
|
||||||
const shouldUpdate = this.shouldUpdate(nextProps);
|
const shouldUpdate = this.shouldUpdate(nextProps);
|
||||||
this.props = nextProps;
|
this.props = nextProps;
|
||||||
return shouldUpdate ? this.render() : Promise.resolve();
|
return shouldUpdate ? this.render() : Promise.resolve();
|
||||||
@@ -205,7 +205,7 @@ export class Widget<T extends WEnv> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private visitSubTree(callback: (w: Widget<T>) => void) {
|
private visitSubTree(callback: (w: Widget<T, any>) => void) {
|
||||||
callback(this);
|
callback(this);
|
||||||
const children = this.__widget__.children;
|
const children = this.__widget__.children;
|
||||||
for (let id in children) {
|
for (let id in children) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Type } from "./types";
|
|||||||
// Types
|
// Types
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
type ActionWidget = Type<Widget<Env>>;
|
type ActionWidget = Type<Widget<Env, {}>>;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Registry code
|
// Registry code
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export type Action = ClientAction | ActWindowAction;
|
|||||||
|
|
||||||
export interface ActionWidget {
|
export interface ActionWidget {
|
||||||
id: number;
|
id: number;
|
||||||
Widget: Type<Widget<Env>>;
|
Widget: Type<Widget<Env, {}>>;
|
||||||
props: any;
|
props: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const template = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export class CRM extends Widget<Env> {
|
export class CRM extends Widget<Env, {}> {
|
||||||
name = "crm";
|
name = "crm";
|
||||||
template = template;
|
template = template;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,19 @@ const template = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export class Counter extends Widget<Env> {
|
interface Props {
|
||||||
|
initialState?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Counter extends Widget<Env, Props> {
|
||||||
name = "counter";
|
name = "counter";
|
||||||
template = template;
|
template = template;
|
||||||
state = {
|
state = {
|
||||||
counter: 0
|
counter: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(parent: Widget<Env>, props: { initialState?: number }) {
|
constructor(parent: Widget<Env, {}>, props: Props) {
|
||||||
super(parent);
|
super(parent, props);
|
||||||
this.state.counter = props.initialState || 0;
|
this.state.counter = props.initialState || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const template = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export class Discuss extends Widget<Env> {
|
export class Discuss extends Widget<Env, {}> {
|
||||||
name = "discuss";
|
name = "discuss";
|
||||||
template = template;
|
template = template;
|
||||||
widgets = { Clock, Counter, ColorWidget };
|
widgets = { Clock, Counter, ColorWidget };
|
||||||
@@ -54,7 +54,7 @@ export class Discuss extends Widget<Env> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColorWidget extends Widget<Env> {
|
class ColorWidget extends Widget<Env, { color: "red" | "blue" }> {
|
||||||
name = "colorwidget";
|
name = "colorwidget";
|
||||||
template = `<div>Current Color: <t t-esc="props.color"/></div>`;
|
template = `<div>Current Color: <t t-esc="props.color"/></div>`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const template = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export class Navbar extends Widget<Env> {
|
export class Navbar extends Widget<Env, {}> {
|
||||||
name = "navbar";
|
name = "navbar";
|
||||||
template = template;
|
template = template;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Env } from "../env";
|
|||||||
|
|
||||||
const template = `<div class="o_clock"><t t-esc="state.currentTime"/></div>`;
|
const template = `<div class="o_clock"><t t-esc="state.currentTime"/></div>`;
|
||||||
|
|
||||||
export class Clock extends Widget<Env> {
|
export class Clock extends Widget<Env, {}> {
|
||||||
name = "clock";
|
name = "clock";
|
||||||
template = template;
|
template = template;
|
||||||
interval: any | undefined;
|
interval: any | undefined;
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ const template = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export class RootWidget extends Widget<Env> {
|
export class RootWidget extends Widget<Env, {}> {
|
||||||
name = "root";
|
name = "root";
|
||||||
template = template;
|
template = template;
|
||||||
widgets = { Navbar };
|
widgets = { Navbar };
|
||||||
content: Widget<Env> | null = null;
|
content: Widget<Env, {}> | null = null;
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.env.actionManager.on("action_ready", this, this.setContentWidget);
|
this.env.actionManager.on("action_ready", this, this.setContentWidget);
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ function nextTick(): Promise<void> {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
function children(w: Widget<WEnv>): Widget<WEnv>[] {
|
function children(w: Widget<WEnv, {}>): Widget<WEnv, {}>[] {
|
||||||
const childrenMap = w.__widget__.children;
|
const childrenMap = w.__widget__.children;
|
||||||
return Object.keys(childrenMap).map(id => childrenMap[id]);
|
return Object.keys(childrenMap).map(id => childrenMap[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test widgets
|
// Test widgets
|
||||||
class Counter extends Widget<WEnv> {
|
class Counter extends Widget<WEnv, {}> {
|
||||||
name = "counter";
|
name = "counter";
|
||||||
template = `<div><t t-esc="state.counter"/><button t-on-click="inc">Inc</button></div>`;
|
template = `<div><t t-esc="state.counter"/><button t-on-click="inc">Inc</button></div>`;
|
||||||
state = {
|
state = {
|
||||||
@@ -49,13 +49,13 @@ class Counter extends Widget<WEnv> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WidgetA extends Widget<WEnv> {
|
class WidgetA extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
template = `<div>Hello<t t-widget="b"/></div>`;
|
template = `<div>Hello<t t-widget="b"/></div>`;
|
||||||
widgets = { b: WidgetB };
|
widgets = { b: WidgetB };
|
||||||
}
|
}
|
||||||
|
|
||||||
class WidgetB extends Widget<WEnv> {
|
class WidgetB extends Widget<WEnv, {}> {
|
||||||
template = `<div>world</div>`;
|
template = `<div>world</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ describe("basic widget properties", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("widget style and classname", async () => {
|
test("widget style and classname", async () => {
|
||||||
class StyledWidget extends Widget<WEnv> {
|
class StyledWidget extends Widget<WEnv, {}> {
|
||||||
template = `<div style="font-weight:bold;" class="some-class">world</div>`;
|
template = `<div style="font-weight:bold;" class="some-class">world</div>`;
|
||||||
}
|
}
|
||||||
const widget = new StyledWidget(env);
|
const widget = new StyledWidget(env);
|
||||||
@@ -99,7 +99,7 @@ describe("basic widget properties", () => {
|
|||||||
|
|
||||||
test("updateState before first render does not trigger a render", async () => {
|
test("updateState before first render does not trigger a render", async () => {
|
||||||
let renderCalls = 0;
|
let renderCalls = 0;
|
||||||
class TestW extends Widget<WEnv> {
|
class TestW extends Widget<WEnv, {}> {
|
||||||
async willStart() {
|
async willStart() {
|
||||||
this.updateState({});
|
this.updateState({});
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ describe("basic widget properties", () => {
|
|||||||
describe("lifecycle hooks", () => {
|
describe("lifecycle hooks", () => {
|
||||||
test("willStart hook is called", async () => {
|
test("willStart hook is called", async () => {
|
||||||
let willstart = false;
|
let willstart = false;
|
||||||
class HookWidget extends Widget<WEnv> {
|
class HookWidget extends Widget<WEnv, {}> {
|
||||||
async willStart() {
|
async willStart() {
|
||||||
willstart = true;
|
willstart = true;
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
test("mounted hook is not called if not in DOM", async () => {
|
test("mounted hook is not called if not in DOM", async () => {
|
||||||
let mounted = false;
|
let mounted = false;
|
||||||
class HookWidget extends Widget<WEnv> {
|
class HookWidget extends Widget<WEnv, {}> {
|
||||||
async mounted() {
|
async mounted() {
|
||||||
mounted = true;
|
mounted = true;
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
test("mounted hook is called if mounted in DOM", async () => {
|
test("mounted hook is called if mounted in DOM", async () => {
|
||||||
let mounted = false;
|
let mounted = false;
|
||||||
class HookWidget extends Widget<WEnv> {
|
class HookWidget extends Widget<WEnv, {}> {
|
||||||
async mounted() {
|
async mounted() {
|
||||||
mounted = true;
|
mounted = true;
|
||||||
}
|
}
|
||||||
@@ -169,12 +169,12 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
test("willStart hook is called on subwidget", async () => {
|
test("willStart hook is called on subwidget", async () => {
|
||||||
let ok = false;
|
let ok = false;
|
||||||
class ParentWidget extends Widget<WEnv> {
|
class ParentWidget extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
template = `<div><t t-widget="child"/></div>`;
|
template = `<div><t t-widget="child"/></div>`;
|
||||||
widgets = { child: ChildWidget };
|
widgets = { child: ChildWidget };
|
||||||
}
|
}
|
||||||
class ChildWidget extends Widget<WEnv> {
|
class ChildWidget extends Widget<WEnv, {}> {
|
||||||
async willStart() {
|
async willStart() {
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@ describe("lifecycle hooks", () => {
|
|||||||
expect.assertions(4);
|
expect.assertions(4);
|
||||||
let parentMounted = false;
|
let parentMounted = false;
|
||||||
let childMounted = false;
|
let childMounted = false;
|
||||||
class ParentWidget extends Widget<WEnv> {
|
class ParentWidget extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
template = `<div><t t-widget="child"/></div>`;
|
template = `<div><t t-widget="child"/></div>`;
|
||||||
widgets = { child: ChildWidget };
|
widgets = { child: ChildWidget };
|
||||||
@@ -197,7 +197,7 @@ describe("lifecycle hooks", () => {
|
|||||||
parentMounted = true;
|
parentMounted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class ChildWidget extends Widget<WEnv> {
|
class ChildWidget extends Widget<WEnv, {}> {
|
||||||
mounted() {
|
mounted() {
|
||||||
expect(document.body.contains(this.el)).toBe(true);
|
expect(document.body.contains(this.el)).toBe(true);
|
||||||
expect(parentMounted).toBe(true);
|
expect(parentMounted).toBe(true);
|
||||||
@@ -212,7 +212,7 @@ describe("lifecycle hooks", () => {
|
|||||||
test("willStart, mounted on subwidget rendered after main is mounted in some other position", async () => {
|
test("willStart, mounted on subwidget rendered after main is mounted in some other position", async () => {
|
||||||
expect.assertions(3);
|
expect.assertions(3);
|
||||||
let hookCounter = 0;
|
let hookCounter = 0;
|
||||||
class ParentWidget extends Widget<WEnv> {
|
class ParentWidget extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
state = { ok: false };
|
state = { ok: false };
|
||||||
template = `
|
template = `
|
||||||
@@ -228,7 +228,7 @@ describe("lifecycle hooks", () => {
|
|||||||
// patching algorithm
|
// patching algorithm
|
||||||
widgets = { child: ChildWidget };
|
widgets = { child: ChildWidget };
|
||||||
}
|
}
|
||||||
class ChildWidget extends Widget<WEnv> {
|
class ChildWidget extends Widget<WEnv, {}> {
|
||||||
async willStart() {
|
async willStart() {
|
||||||
hookCounter++;
|
hookCounter++;
|
||||||
}
|
}
|
||||||
@@ -253,14 +253,14 @@ describe("lifecycle hooks", () => {
|
|||||||
expect.assertions(1);
|
expect.assertions(1);
|
||||||
const target = document.createElement("div");
|
const target = document.createElement("div");
|
||||||
document.body.appendChild(target);
|
document.body.appendChild(target);
|
||||||
class ParentWidget extends Widget<WEnv> {
|
class ParentWidget extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
mounted() {
|
mounted() {
|
||||||
const child = new ChildWidget(this);
|
const child = new ChildWidget(this);
|
||||||
child.mount(this.el!);
|
child.mount(this.el!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class ChildWidget extends Widget<WEnv> {
|
class ChildWidget extends Widget<WEnv, {}> {
|
||||||
mounted() {
|
mounted() {
|
||||||
expect(this.el).toBeTruthy();
|
expect(this.el).toBeTruthy();
|
||||||
done();
|
done();
|
||||||
@@ -272,7 +272,7 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
test("widgets are unmounted and destroyed if no longer in DOM", async () => {
|
test("widgets are unmounted and destroyed if no longer in DOM", async () => {
|
||||||
let steps: string[] = [];
|
let steps: string[] = [];
|
||||||
class ParentWidget extends Widget<WEnv> {
|
class ParentWidget extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
state = { ok: true };
|
state = { ok: true };
|
||||||
template = `
|
template = `
|
||||||
@@ -282,7 +282,7 @@ describe("lifecycle hooks", () => {
|
|||||||
widgets = { child: ChildWidget };
|
widgets = { child: ChildWidget };
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChildWidget extends Widget<WEnv> {
|
class ChildWidget extends Widget<WEnv, {}> {
|
||||||
constructor(parent) {
|
constructor(parent) {
|
||||||
super(parent);
|
super(parent);
|
||||||
steps.push("init");
|
steps.push("init");
|
||||||
@@ -315,7 +315,7 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
test("hooks are called in proper order in widget creation/destruction", async () => {
|
test("hooks are called in proper order in widget creation/destruction", async () => {
|
||||||
let steps: string[] = [];
|
let steps: string[] = [];
|
||||||
class ParentWidget extends Widget<WEnv> {
|
class ParentWidget extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
template = `
|
template = `
|
||||||
<div><t t-widget="child"/></div>`;
|
<div><t t-widget="child"/></div>`;
|
||||||
@@ -338,7 +338,7 @@ describe("lifecycle hooks", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChildWidget extends Widget<WEnv> {
|
class ChildWidget extends Widget<WEnv, {}> {
|
||||||
constructor(parent) {
|
constructor(parent) {
|
||||||
super(parent);
|
super(parent);
|
||||||
steps.push("c init");
|
steps.push("c init");
|
||||||
@@ -375,7 +375,7 @@ describe("lifecycle hooks", () => {
|
|||||||
|
|
||||||
test("shouldUpdate hook prevent rerendering", async () => {
|
test("shouldUpdate hook prevent rerendering", async () => {
|
||||||
let shouldUpdate = false;
|
let shouldUpdate = false;
|
||||||
class TestWidget extends Widget<WEnv> {
|
class TestWidget extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
template = `<div><t t-esc="props.val"/></div>`;
|
template = `<div><t t-esc="props.val"/></div>`;
|
||||||
shouldUpdate() {
|
shouldUpdate() {
|
||||||
@@ -406,7 +406,7 @@ describe("destroy method", () => {
|
|||||||
|
|
||||||
test("destroying a widget twice only call destroyed once", async () => {
|
test("destroying a widget twice only call destroyed once", async () => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
class TestWidget extends Widget<WEnv> {
|
class TestWidget extends Widget<WEnv, {}> {
|
||||||
destroyed() {
|
destroyed() {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@@ -448,7 +448,7 @@ describe("destroy method", () => {
|
|||||||
let p: Promise<void> = new Promise(function(r) {
|
let p: Promise<void> = new Promise(function(r) {
|
||||||
resolve = r;
|
resolve = r;
|
||||||
});
|
});
|
||||||
class DelayedWidget extends Widget<WEnv> {
|
class DelayedWidget extends Widget<WEnv, {}> {
|
||||||
willStart() {
|
willStart() {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -488,7 +488,7 @@ describe("composition", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("t-refs on widget are widgets", async () => {
|
test("t-refs on widget are widgets", async () => {
|
||||||
class WidgetC extends Widget<WEnv> {
|
class WidgetC extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
template = `<div>Hello<t t-ref="mywidgetb" t-widget="b"/></div>`;
|
template = `<div>Hello<t t-ref="mywidgetb" t-widget="b"/></div>`;
|
||||||
widgets = { b: WidgetB };
|
widgets = { b: WidgetB };
|
||||||
@@ -499,7 +499,7 @@ describe("composition", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("modifying a sub widget", async () => {
|
test("modifying a sub widget", async () => {
|
||||||
class ParentWidget extends Widget<WEnv> {
|
class ParentWidget extends Widget<WEnv, {}> {
|
||||||
template = `<div><t t-widget="Counter"/></div>`;
|
template = `<div><t t-widget="Counter"/></div>`;
|
||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
}
|
}
|
||||||
@@ -537,7 +537,7 @@ describe("composition", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("rerendering a widget with a sub widget", async () => {
|
test("rerendering a widget with a sub widget", async () => {
|
||||||
class ParentWidget extends Widget<WEnv> {
|
class ParentWidget extends Widget<WEnv, {}> {
|
||||||
template = `<div><t t-widget="Counter"/></div>`;
|
template = `<div><t t-widget="Counter"/></div>`;
|
||||||
widgets = { Counter };
|
widgets = { Counter };
|
||||||
}
|
}
|
||||||
@@ -556,7 +556,7 @@ describe("composition", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("sub widgets are destroyed if no longer in dom, then recreated", async () => {
|
test("sub widgets are destroyed if no longer in dom, then recreated", async () => {
|
||||||
class ParentWidget extends Widget<WEnv> {
|
class ParentWidget extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
state = { ok: true };
|
state = { ok: true };
|
||||||
template = `
|
template = `
|
||||||
@@ -582,14 +582,14 @@ describe("composition", () => {
|
|||||||
|
|
||||||
describe("props evaluation (with t-props directive)", () => {
|
describe("props evaluation (with t-props directive)", () => {
|
||||||
test("explicit object prop", async () => {
|
test("explicit object prop", async () => {
|
||||||
class Parent extends Widget<WEnv> {
|
class Parent extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
template = `<div><t t-widget="child" t-props="{value: state.val}"/></div>`;
|
template = `<div><t t-widget="child" t-props="{value: state.val}"/></div>`;
|
||||||
widgets = { child: Child };
|
widgets = { child: Child };
|
||||||
state = { val: 42 };
|
state = { val: 42 };
|
||||||
}
|
}
|
||||||
|
|
||||||
class Child extends Widget<WEnv> {
|
class Child extends Widget<WEnv, {}> {
|
||||||
template = `<span><t t-esc="state.someval"/></span>`;
|
template = `<span><t t-esc="state.someval"/></span>`;
|
||||||
state: { someval: number };
|
state: { someval: number };
|
||||||
constructor(parent: Parent, props: { value: number }) {
|
constructor(parent: Parent, props: { value: number }) {
|
||||||
@@ -604,14 +604,14 @@ describe("props evaluation (with t-props directive)", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("object prop value", async () => {
|
test("object prop value", async () => {
|
||||||
class Parent extends Widget<WEnv> {
|
class Parent extends Widget<WEnv, {}> {
|
||||||
name = "a";
|
name = "a";
|
||||||
template = `<div><t t-widget="child" t-props="state"/></div>`;
|
template = `<div><t t-widget="child" t-props="state"/></div>`;
|
||||||
widgets = { child: Child };
|
widgets = { child: Child };
|
||||||
state = { val: 42 };
|
state = { val: 42 };
|
||||||
}
|
}
|
||||||
|
|
||||||
class Child extends Widget<WEnv> {
|
class Child extends Widget<WEnv, {}> {
|
||||||
template = `<span><t t-esc="state.someval"/></span>`;
|
template = `<span><t t-esc="state.someval"/></span>`;
|
||||||
state: { someval: number };
|
state: { someval: number };
|
||||||
constructor(parent: Parent, props: { val: number }) {
|
constructor(parent: Parent, props: { val: number }) {
|
||||||
|
|||||||
Reference in New Issue
Block a user