mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
committed by
Géry Debongnie
parent
8ee0973dab
commit
0aba9748c9
@@ -19,6 +19,7 @@
|
||||
- [`t-ref` directive](#t-ref-directive)
|
||||
- [`t-key` directive](#t-key-directive)
|
||||
- [`t-transition` directive](#t-transition-directive)
|
||||
- [`t-mounted` directive](#t-mounted-directive)
|
||||
- [Debugging (`t-debug` and `t-log`)](#debugging-t-debug-and-t-log)
|
||||
- [White spaces](#white-spaces)
|
||||
- [Root nodes](#root-nodes)
|
||||
@@ -352,6 +353,11 @@ For example, a simple fade in/out effect can be done with this:
|
||||
|
||||
Note: more information on animations are available [here](doc/animations.md).
|
||||
|
||||
### `t-mounted` directive
|
||||
|
||||
The `t-mounted` directive allows to register a callback to execute when the node
|
||||
is inserted into the DOM.
|
||||
|
||||
### Debugging (`t-debug` and `t-log`)
|
||||
|
||||
The javascript QWeb implementation provides two useful debugging directives:
|
||||
|
||||
+7
-1
@@ -40,6 +40,7 @@ export interface Meta<T extends Env, Props> {
|
||||
boundHandlers: { [key: number]: any };
|
||||
observer?: Observer;
|
||||
render?: CompiledTemplate;
|
||||
mountedHandlers: { [key: number]: Function };
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -119,7 +120,8 @@ export class Component<
|
||||
renderId: 1,
|
||||
renderPromise: null,
|
||||
renderProps: props || null,
|
||||
boundHandlers: {}
|
||||
boundHandlers: {},
|
||||
mountedHandlers: {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -226,6 +228,9 @@ export class Component<
|
||||
}
|
||||
}
|
||||
this.__owl__.isMounted = true;
|
||||
for (let key in this.__owl__.mountedHandlers) {
|
||||
this.__owl__.mountedHandlers[key]();
|
||||
}
|
||||
this.mounted();
|
||||
}
|
||||
|
||||
@@ -400,6 +405,7 @@ export class Component<
|
||||
let vnode = this.__owl__.render!(this, {
|
||||
promises,
|
||||
handlers: this.__owl__.boundHandlers,
|
||||
mountedHandlers: this.__owl__.mountedHandlers,
|
||||
forceUpdate: force,
|
||||
patchQueue
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import { QWeb, UTILS } from "./qweb_core";
|
||||
* - t-ref
|
||||
* - t-transition
|
||||
* - t-widget/t-props/t-keepalive
|
||||
* - t-mounted
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -325,3 +326,41 @@ QWeb.addDirective({
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// t-mounted
|
||||
//------------------------------------------------------------------------------
|
||||
QWeb.addDirective({
|
||||
name: "mounted",
|
||||
priority: 97,
|
||||
atNodeCreation({ ctx, fullName, value, nodeID }) {
|
||||
ctx.rootContext.shouldDefineOwner = true;
|
||||
const eventName = fullName.slice(5);
|
||||
if (!eventName) {
|
||||
throw new Error("Missing event name with t-on directive");
|
||||
}
|
||||
let extraArgs;
|
||||
let handler = value.replace(/\(.*\)/, function(args) {
|
||||
extraArgs = args.slice(1, -1);
|
||||
return "";
|
||||
});
|
||||
let error = `(function () {throw new Error('Missing handler \\'' + '${handler}' + \`\\' when evaluating template '${ctx.templateName.replace(
|
||||
/`/g,
|
||||
"'"
|
||||
)}'\`)})()`;
|
||||
if (extraArgs) {
|
||||
ctx.addLine(
|
||||
`extra.mountedHandlers[${nodeID}] = (context['${handler}'] || ${error}).bind(owner, ${ctx.formatExpression(
|
||||
extraArgs
|
||||
)});`
|
||||
);
|
||||
} else {
|
||||
ctx.addLine(
|
||||
`extra.mountedHandlers[${nodeID}] = extra.mountedHandlers[${nodeID}] || (context['${handler}'] || ${error}).bind(owner);`
|
||||
);
|
||||
}
|
||||
ctx.addLine(`p${nodeID}.hook = {
|
||||
insert: (vn) => { if (context.__owl__.isMounted) { extra.mountedHandlers[${nodeID}](); } },
|
||||
};`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -2013,3 +2013,55 @@ describe("widget and observable state", () => {
|
||||
expect(fixture.innerHTML).toBe("<div>12</div>");
|
||||
});
|
||||
});
|
||||
|
||||
describe("t-mounted directive", () => {
|
||||
test("callback is not called when not in DOM", async () => {
|
||||
class TestWidget extends Widget {
|
||||
inlineTemplate = `<div><input t-mounted="f"/></div>`;
|
||||
f() {}
|
||||
}
|
||||
const widget = new TestWidget(env);
|
||||
widget.f = jest.fn();
|
||||
await widget.mount(document.createElement("div"));
|
||||
expect(widget.f).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("callback is called when in DOM", async () => {
|
||||
class TestWidget extends Widget {
|
||||
inlineTemplate = `<div><input t-mounted="f"/></div>`;
|
||||
f() {}
|
||||
}
|
||||
const widget = new TestWidget(env);
|
||||
widget.f = jest.fn();
|
||||
await widget.mount(fixture);
|
||||
expect(widget.f).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("callback with args is called when in DOM", async () => {
|
||||
class TestWidget extends Widget {
|
||||
inlineTemplate = `<div><input t-mounted="f(2)"/></div>`;
|
||||
f() {}
|
||||
}
|
||||
const widget = new TestWidget(env);
|
||||
widget.f = jest.fn();
|
||||
await widget.mount(fixture);
|
||||
expect(widget.f).toHaveBeenCalledTimes(1);
|
||||
expect(widget.f).toHaveBeenCalledWith(2);
|
||||
});
|
||||
|
||||
test("combined with a t-if", async () => {
|
||||
class TestWidget extends Widget {
|
||||
inlineTemplate = `<div><input t-if="state.flag" t-mounted="f"/></div>`;
|
||||
state = { flag: false };
|
||||
f() {}
|
||||
}
|
||||
const widget = new TestWidget(env);
|
||||
widget.f = jest.fn();
|
||||
await widget.mount(fixture);
|
||||
expect(widget.f).toHaveBeenCalledTimes(0);
|
||||
|
||||
widget.state.flag = true;
|
||||
await nextTick();
|
||||
expect(widget.f).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user