mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] add support for t-call-context directive
This commit is contained in:
@@ -540,6 +540,15 @@ This can be used to define variables scoped to a sub template:
|
|||||||
<!-- "var" does not exist here -->
|
<!-- "var" does not exist here -->
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: by default, the rendering context for a sub template is simply the current
|
||||||
|
rendering context (so, the current component). However, it may be useful to be
|
||||||
|
able to specify a specific object as context. This can be done by using the
|
||||||
|
`t-call-context` directive:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<t t-call="other-template" t-call-context="obj"/>
|
||||||
|
```
|
||||||
|
|
||||||
### Dynamic sub templates
|
### Dynamic sub templates
|
||||||
|
|
||||||
The `t-call` directive can also be used to dynamically call a sub template,
|
The `t-call` directive can also be used to dynamically call a sub template,
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ interface Context {
|
|||||||
tKeyExpr: string | null;
|
tKeyExpr: string | null;
|
||||||
nameSpace?: string;
|
nameSpace?: string;
|
||||||
tModelSelectedExpr?: string;
|
tModelSelectedExpr?: string;
|
||||||
|
ctxVar?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createContext(parentCtx: Context, params?: Partial<Context>) {
|
function createContext(parentCtx: Context, params?: Partial<Context>) {
|
||||||
@@ -967,16 +968,21 @@ export class CodeGenerator {
|
|||||||
|
|
||||||
compileTCall(ast: ASTTCall, ctx: Context) {
|
compileTCall(ast: ASTTCall, ctx: Context) {
|
||||||
let { block, forceNewBlock } = ctx;
|
let { block, forceNewBlock } = ctx;
|
||||||
|
let ctxVar = ctx.ctxVar || "ctx";
|
||||||
|
if (ast.context) {
|
||||||
|
ctxVar = generateId("ctx");
|
||||||
|
this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);
|
||||||
|
}
|
||||||
if (ast.body) {
|
if (ast.body) {
|
||||||
this.addLine(`ctx = Object.create(ctx);`);
|
this.addLine(`${ctxVar} = Object.create(${ctxVar});`);
|
||||||
this.addLine(`ctx[isBoundary] = 1;`);
|
this.addLine(`${ctxVar}[isBoundary] = 1;`);
|
||||||
this.helpers.add("isBoundary");
|
this.helpers.add("isBoundary");
|
||||||
const nextId = BlockDescription.nextBlockId;
|
const nextId = BlockDescription.nextBlockId;
|
||||||
const subCtx: Context = createContext(ctx, { preventRoot: true });
|
const subCtx: Context = createContext(ctx, { preventRoot: true, ctxVar });
|
||||||
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
|
this.compileAST({ type: ASTType.Multi, content: ast.body }, subCtx);
|
||||||
if (nextId !== BlockDescription.nextBlockId) {
|
if (nextId !== BlockDescription.nextBlockId) {
|
||||||
this.helpers.add("zero");
|
this.helpers.add("zero");
|
||||||
this.addLine(`ctx[zero] = b${nextId};`);
|
this.addLine(`${ctxVar}[zero] = b${nextId};`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isDynamic = INTERP_REGEXP.test(ast.name);
|
const isDynamic = INTERP_REGEXP.test(ast.name);
|
||||||
@@ -994,7 +1000,7 @@ export class CodeGenerator {
|
|||||||
}
|
}
|
||||||
this.define(templateVar, subTemplate);
|
this.define(templateVar, subTemplate);
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(`call(this, ${templateVar}, ctx, node, ${key})`, block!, {
|
this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`, block!, {
|
||||||
...ctx,
|
...ctx,
|
||||||
forceNewBlock: !block,
|
forceNewBlock: !block,
|
||||||
});
|
});
|
||||||
@@ -1002,13 +1008,13 @@ export class CodeGenerator {
|
|||||||
const id = generateId(`callTemplate_`);
|
const id = generateId(`callTemplate_`);
|
||||||
this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` });
|
this.staticDefs.push({ id, expr: `app.getTemplate(${subTemplate})` });
|
||||||
block = this.createBlock(block, "multi", ctx);
|
block = this.createBlock(block, "multi", ctx);
|
||||||
this.insertBlock(`${id}.call(this, ctx, node, ${key})`, block!, {
|
this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`, block!, {
|
||||||
...ctx,
|
...ctx,
|
||||||
forceNewBlock: !block,
|
forceNewBlock: !block,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (ast.body && !ctx.isLast) {
|
if (ast.body && !ctx.isLast) {
|
||||||
this.addLine(`ctx = ctx.__proto__;`);
|
this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1046,7 +1052,7 @@ export class CodeGenerator {
|
|||||||
value = expr;
|
value = expr;
|
||||||
}
|
}
|
||||||
this.helpers.add("setContextValue");
|
this.helpers.add("setContextValue");
|
||||||
this.addLine(`setContextValue(ctx, "${ast.name}", ${value});`);
|
this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ export interface ASTTCall {
|
|||||||
type: ASTType.TCall;
|
type: ASTType.TCall;
|
||||||
name: string;
|
name: string;
|
||||||
body: AST[] | null;
|
body: AST[] | null;
|
||||||
|
context: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SlotDefinition {
|
interface SlotDefinition {
|
||||||
@@ -557,11 +558,13 @@ function parseTCall(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const subTemplate = node.getAttribute("t-call")!;
|
const subTemplate = node.getAttribute("t-call")!;
|
||||||
|
const context = node.getAttribute("t-call-context");
|
||||||
node.removeAttribute("t-call");
|
node.removeAttribute("t-call");
|
||||||
|
node.removeAttribute("t-call-context");
|
||||||
|
|
||||||
if (node.tagName !== "t") {
|
if (node.tagName !== "t") {
|
||||||
const ast = parseNode(node, ctx);
|
const ast = parseNode(node, ctx);
|
||||||
const tcall: AST = { type: ASTType.TCall, name: subTemplate, body: null };
|
const tcall: AST = { type: ASTType.TCall, name: subTemplate, body: null, context };
|
||||||
if (ast && ast.type === ASTType.DomNode) {
|
if (ast && ast.type === ASTType.DomNode) {
|
||||||
ast.content = [tcall];
|
ast.content = [tcall];
|
||||||
return ast;
|
return ast;
|
||||||
@@ -579,6 +582,7 @@ function parseTCall(node: Element, ctx: ParsingContext): AST | null {
|
|||||||
type: ASTType.TCall,
|
type: ASTType.TCall,
|
||||||
name: subTemplate,
|
name: subTemplate,
|
||||||
body: body.length ? body : null,
|
body: body.length ? body : null,
|
||||||
|
context,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -617,6 +617,36 @@ exports[`t-call (template calling) t-call allowed on a non t node 2`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) t-call on a div with t-call-context 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`sub\`);
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<div><block-child-0/></div>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let ctx1 = ctx['obj'];
|
||||||
|
const b2 = callTemplate_1.call(this, ctx1, node, key + \`__1\`);
|
||||||
|
return block1([], [b2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) t-call on a div with t-call-context 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<span><block-text-0/></span>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let txt1 = ctx['value'];
|
||||||
|
return block1([txt1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-call (template calling) t-call with body content as root of a template 1`] = `
|
exports[`t-call (template calling) t-call with body content as root of a template 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
@@ -890,6 +920,67 @@ exports[`t-call (template calling) t-call, conditional and t-set in t-call body
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) t-call-context 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`sub\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let ctx1 = ctx['obj'];
|
||||||
|
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) t-call-context 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<span><block-text-0/></span>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let txt1 = ctx['value'];
|
||||||
|
return block1([txt1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) t-call-context and value in body 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
let { isBoundary, withDefault, setContextValue } = helpers;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`sub\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
ctx = Object.create(ctx);
|
||||||
|
ctx[isBoundary] = 1
|
||||||
|
let ctx1 = ctx['obj'];
|
||||||
|
ctx1 = Object.create(ctx1);
|
||||||
|
ctx1[isBoundary] = 1;
|
||||||
|
setContextValue(ctx1, \\"value2\\", ctx['aaron']);
|
||||||
|
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling) t-call-context and value in body 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<span><block-text-0/><block-text-1/></span>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let txt1 = ctx['value1'];
|
||||||
|
let txt2 = ctx['value2'];
|
||||||
|
return block1([txt1, txt2]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-call (template calling) t-esc inside t-call, with t-set outside 1`] = `
|
exports[`t-call (template calling) t-esc inside t-call, with t-set outside 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1033,6 +1033,7 @@ describe("qweb parser", () => {
|
|||||||
type: ASTType.TCall,
|
type: ASTType.TCall,
|
||||||
name: "blap",
|
name: "blap",
|
||||||
body: null,
|
body: null,
|
||||||
|
context: null,
|
||||||
},
|
},
|
||||||
memo: "",
|
memo: "",
|
||||||
hasNoFirst: false,
|
hasNoFirst: false,
|
||||||
@@ -1070,6 +1071,7 @@ describe("qweb parser", () => {
|
|||||||
type: ASTType.TCall,
|
type: ASTType.TCall,
|
||||||
name: "blabla",
|
name: "blabla",
|
||||||
body: null,
|
body: null,
|
||||||
|
context: null,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1077,10 +1079,20 @@ describe("qweb parser", () => {
|
|||||||
expect(parse(`<t t-call="sub">ok</t>`)).toEqual({
|
expect(parse(`<t t-call="sub">ok</t>`)).toEqual({
|
||||||
type: ASTType.TCall,
|
type: ASTType.TCall,
|
||||||
name: "sub",
|
name: "sub",
|
||||||
|
context: null,
|
||||||
body: [{ type: ASTType.Text, value: "ok" }],
|
body: [{ type: ASTType.Text, value: "ok" }],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("t-call expression with t-call-context", async () => {
|
||||||
|
expect(parse(`<t t-call="blabla" t-call-context="someContext"/>`)).toEqual({
|
||||||
|
type: ASTType.TCall,
|
||||||
|
name: "blabla",
|
||||||
|
body: null,
|
||||||
|
context: "someContext",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("t-call on a div node", async () => {
|
test("t-call on a div node", async () => {
|
||||||
expect(parse(`<div t-call="blabla" />`)).toEqual({
|
expect(parse(`<div t-call="blabla" />`)).toEqual({
|
||||||
type: ASTType.DomNode,
|
type: ASTType.DomNode,
|
||||||
@@ -1096,6 +1108,7 @@ describe("qweb parser", () => {
|
|||||||
type: ASTType.TCall,
|
type: ASTType.TCall,
|
||||||
name: "blabla",
|
name: "blabla",
|
||||||
body: null,
|
body: null,
|
||||||
|
context: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -1111,6 +1124,7 @@ describe("qweb parser", () => {
|
|||||||
type: ASTType.TCall,
|
type: ASTType.TCall,
|
||||||
name: "blabla",
|
name: "blabla",
|
||||||
body: null,
|
body: null,
|
||||||
|
context: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1547,7 +1561,7 @@ describe("qweb parser", () => {
|
|||||||
on: null,
|
on: null,
|
||||||
slots: {
|
slots: {
|
||||||
default: {
|
default: {
|
||||||
content: { body: null, name: "subTemplate", type: ASTType.TCall },
|
content: { body: null, name: "subTemplate", type: ASTType.TCall, context: null },
|
||||||
attrs: null,
|
attrs: null,
|
||||||
scope: null,
|
scope: null,
|
||||||
on: null,
|
on: null,
|
||||||
|
|||||||
@@ -445,4 +445,38 @@ describe("t-call (template calling)", () => {
|
|||||||
const expected2 = "<div><bar>quux</bar></div>";
|
const expected2 = "<div><bar>quux</bar></div>";
|
||||||
expect(context.renderToString("main", { template: "bar", val: "quux" })).toBe(expected2);
|
expect(context.renderToString("main", { template: "bar", val: "quux" })).toBe(expected2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("t-call-context", () => {
|
||||||
|
const context = new TestContext();
|
||||||
|
context.addTemplate("sub", `<span><t t-esc="value"/></span>`);
|
||||||
|
context.addTemplate("main", `<t t-call="sub" t-call-context="obj"/>`);
|
||||||
|
|
||||||
|
expect(context.renderToString("main", { obj: { value: 123 } })).toBe("<span>123</span>");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-call on a div with t-call-context", () => {
|
||||||
|
const context = new TestContext();
|
||||||
|
context.addTemplate("sub", `<span><t t-esc="value"/></span>`);
|
||||||
|
context.addTemplate("main", `<div t-call="sub" t-call-context="obj"/>`);
|
||||||
|
|
||||||
|
expect(context.renderToString("main", { obj: { value: 123 } })).toBe(
|
||||||
|
"<div><span>123</span></div>"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-call-context and value in body", () => {
|
||||||
|
const context = new TestContext();
|
||||||
|
context.addTemplate("sub", `<span><t t-esc="value1"/><t t-esc="value2"/></span>`);
|
||||||
|
context.addTemplate(
|
||||||
|
"main",
|
||||||
|
`
|
||||||
|
<t t-call="sub" t-call-context="obj">
|
||||||
|
<t t-set="value2" t-value="aaron" />
|
||||||
|
</t>`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(context.renderToString("main", { obj: { value1: 123 }, aaron: "lucas" })).toBe(
|
||||||
|
"<span>123lucas</span>"
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -402,3 +402,70 @@ exports[`t-call t-call in t-foreach and children component 3`] = `
|
|||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-call t-call with t-call-context and subcomponent 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`someTemplate\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let ctx1 = ctx['subctx'];
|
||||||
|
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call t-call with t-call-context and subcomponent 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const comp1 = app.createComponent(\`Child\`, true, false, false, false);
|
||||||
|
const comp2 = app.createComponent(\`Child\`, true, false, false, false);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = comp1({name: ctx['aab']}, key + \`__1\`, node, this, null);
|
||||||
|
const b3 = comp2({name: ctx['lpe']}, key + \`__2\`, node, this, null);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call t-call with t-call-context and subcomponent 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(\`child\`);
|
||||||
|
const b3 = text(ctx['props'].name);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call t-call with t-call-context, simple use 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
const callTemplate_1 = app.getTemplate(\`someTemplate\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let ctx1 = ctx['subctx'];
|
||||||
|
return callTemplate_1.call(this, ctx1, node, key + \`__1\`);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-call t-call with t-call-context, simple use 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
const b2 = text(ctx['aab']);
|
||||||
|
const b3 = text(ctx['lpe']);
|
||||||
|
return multi([b2, b3]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|||||||
@@ -244,4 +244,47 @@ describe("t-call", () => {
|
|||||||
}
|
}
|
||||||
expect(clickCount).toBe(2);
|
expect(clickCount).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("t-call with t-call-context, simple use", async () => {
|
||||||
|
class Root extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-call="someTemplate" t-call-context="subctx"/>`;
|
||||||
|
|
||||||
|
subctx = { aab: "aaron", lpe: "lucas" };
|
||||||
|
}
|
||||||
|
|
||||||
|
await mount(Root, fixture, {
|
||||||
|
templates: `
|
||||||
|
<templates>
|
||||||
|
<t t-name="someTemplate"><t t-esc="aab"/><t t-esc="lpe"/></t>
|
||||||
|
</templates>`,
|
||||||
|
});
|
||||||
|
expect(fixture.innerHTML).toBe("aaronlucas");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-call with t-call-context and subcomponent", async () => {
|
||||||
|
class Child extends Component {
|
||||||
|
static template = xml`child<t t-esc="props.name"/>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Root extends Component {
|
||||||
|
static template = xml`
|
||||||
|
<t t-call="someTemplate" t-call-context="subctx"/>`;
|
||||||
|
|
||||||
|
static components = { Child };
|
||||||
|
|
||||||
|
subctx = { aab: "aaron", lpe: "lucas" };
|
||||||
|
}
|
||||||
|
|
||||||
|
await mount(Root, fixture, {
|
||||||
|
templates: `
|
||||||
|
<templates>
|
||||||
|
<t t-name="someTemplate">
|
||||||
|
<Child name="aab"/>
|
||||||
|
<Child name="lpe"/>
|
||||||
|
</t>
|
||||||
|
</templates>`,
|
||||||
|
});
|
||||||
|
expect(fixture.innerHTML).toBe("childaaronchildlucas");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user