mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] qweb: fix issue variables set in body of t-call
The body of a t-call directive may be used to define private variables to the sub template call. However, the code that handles t-call worked like this: - compile sub template if necessary - then compile body of t-call to extract variables This means that the variables defined in the t-call body were not yet processed and available in the context. Because of that, when the call to t-esc is done, there is not internal qweb var, and the code simply outputs a scope['varname'], which is in our case a VDOMArray, so it is displayed as [object object] What this fix does is changing the way t-esc works: if we are in the context of a sub template, then it assumes that any outside variable may or may not be a VDomArray, so it needs to check and eventually convert it to a string, if necessary. closes #719
This commit is contained in:
@@ -41,6 +41,12 @@ function compileValueNode(value: any, node: Element, qweb: QWeb, ctx: Compilatio
|
|||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
exprID = `_${ctx.generateID()}`;
|
exprID = `_${ctx.generateID()}`;
|
||||||
ctx.addLine(`let ${exprID} = ${ctx.formatExpression(value)};`);
|
ctx.addLine(`let ${exprID} = ${ctx.formatExpression(value)};`);
|
||||||
|
if (ctx.isSubTemplate) {
|
||||||
|
ctx.rootContext.shouldDefineUtils = true;
|
||||||
|
ctx.addLine(
|
||||||
|
`${exprID} = ${exprID} instanceof utils.VDomArray ? utils.vDomToString(${exprID}) : ${exprID};`
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
exprID = `scope.${value.id}`;
|
exprID = `scope.${value.id}`;
|
||||||
}
|
}
|
||||||
@@ -238,7 +244,7 @@ QWeb.addDirective({
|
|||||||
if (!subId) {
|
if (!subId) {
|
||||||
subId = QWeb.nextId++;
|
subId = QWeb.nextId++;
|
||||||
qweb.subTemplates[subTemplate] = subId;
|
qweb.subTemplates[subTemplate] = subId;
|
||||||
const subTemplateFn = qweb._compile(subTemplate, nodeTemplate.elem, ctx, true);
|
const subTemplateFn = qweb._compile(subTemplate, nodeTemplate.elem, ctx, true, true);
|
||||||
QWeb.subTemplates[subId] = subTemplateFn;
|
QWeb.subTemplates[subId] = subTemplateFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export class CompilationContext {
|
|||||||
shouldDefineUtils: boolean = false;
|
shouldDefineUtils: boolean = false;
|
||||||
shouldDefineRefs: boolean = false;
|
shouldDefineRefs: boolean = false;
|
||||||
shouldDefineResult: boolean = true;
|
shouldDefineResult: boolean = true;
|
||||||
|
isSubTemplate: boolean = false;
|
||||||
loopNumber: number = 0;
|
loopNumber: number = 0;
|
||||||
inPreTag: boolean = false;
|
inPreTag: boolean = false;
|
||||||
templateName: string;
|
templateName: string;
|
||||||
|
|||||||
+3
-1
@@ -413,10 +413,12 @@ export class QWeb extends EventBus {
|
|||||||
name: string,
|
name: string,
|
||||||
elem: Element,
|
elem: Element,
|
||||||
parentContext?: CompilationContext,
|
parentContext?: CompilationContext,
|
||||||
defineKey?: boolean
|
defineKey?: boolean,
|
||||||
|
isSubTemplate?: boolean
|
||||||
): CompiledTemplate {
|
): CompiledTemplate {
|
||||||
const isDebug = elem.attributes.hasOwnProperty("t-debug");
|
const isDebug = elem.attributes.hasOwnProperty("t-debug");
|
||||||
const ctx = new CompilationContext(name);
|
const ctx = new CompilationContext(name);
|
||||||
|
ctx.isSubTemplate = Boolean(isSubTemplate);
|
||||||
if (elem.tagName !== "t") {
|
if (elem.tagName !== "t") {
|
||||||
ctx.shouldDefineResult = false;
|
ctx.shouldDefineResult = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1502,6 +1502,7 @@ exports[`t-call (template calling recursive template, part 2 2`] = `
|
|||||||
let vn3 = h('p', p3, c3);
|
let vn3 = h('p', p3, c3);
|
||||||
c2.push(vn3);
|
c2.push(vn3);
|
||||||
let _4 = scope['node'].val;
|
let _4 = scope['node'].val;
|
||||||
|
_4 = _4 instanceof utils.VDomArray ? utils.vDomToString(_4) : _4;
|
||||||
if (_4 != null) {
|
if (_4 != null) {
|
||||||
c3.push({text: _4});
|
c3.push({text: _4});
|
||||||
}
|
}
|
||||||
@@ -1581,6 +1582,7 @@ exports[`t-call (template calling recursive template, part 3 2`] = `
|
|||||||
let vn3 = h('p', p3, c3);
|
let vn3 = h('p', p3, c3);
|
||||||
c2.push(vn3);
|
c2.push(vn3);
|
||||||
let _4 = scope['node'].val;
|
let _4 = scope['node'].val;
|
||||||
|
_4 = _4 instanceof utils.VDomArray ? utils.vDomToString(_4) : _4;
|
||||||
if (_4 != null) {
|
if (_4 != null) {
|
||||||
c3.push({text: _4});
|
c3.push({text: _4});
|
||||||
}
|
}
|
||||||
@@ -1662,6 +1664,7 @@ exports[`t-call (template calling recursive template, part 4: with t-set recursi
|
|||||||
let vn3 = h('p', p3, c3);
|
let vn3 = h('p', p3, c3);
|
||||||
c2.push(vn3);
|
c2.push(vn3);
|
||||||
let _4 = scope['node'].val;
|
let _4 = scope['node'].val;
|
||||||
|
_4 = _4 instanceof utils.VDomArray ? utils.vDomToString(_4) : _4;
|
||||||
if (_4 != null) {
|
if (_4 != null) {
|
||||||
c3.push({text: _4});
|
c3.push({text: _4});
|
||||||
}
|
}
|
||||||
@@ -1752,6 +1755,33 @@ exports[`t-call (template calling t-call with t-if 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-call (template calling t-call with t-set inside and body text content 1`] = `
|
||||||
|
"function anonymous(context, extra
|
||||||
|
) {
|
||||||
|
// Template name: \\"main\\"
|
||||||
|
let utils = this.constructor.utils;
|
||||||
|
let scope = Object.create(context);
|
||||||
|
let h = this.h;
|
||||||
|
let c1 = [], p1 = {key:1};
|
||||||
|
let vn1 = h('div', p1, c1);
|
||||||
|
let _origScope4 = scope;
|
||||||
|
scope = Object.create(scope);
|
||||||
|
scope.__access_mode__ = 'ro';
|
||||||
|
{
|
||||||
|
{
|
||||||
|
let c__0 = [];
|
||||||
|
let c5 = new utils.VDomArray();
|
||||||
|
c5.push({text: \`yip yip\`});
|
||||||
|
scope.val = c5
|
||||||
|
scope[utils.zero] = c__0;
|
||||||
|
}
|
||||||
|
this.constructor.subTemplates['1'].call(this, scope, Object.assign({}, extra, {parentNode: c1, parent: utils.getComponent(context), key: '__6__'}));
|
||||||
|
}
|
||||||
|
scope = _origScope4;
|
||||||
|
return vn1;
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-call (template calling t-call with t-set inside and outside 1`] = `
|
exports[`t-call (template calling t-call with t-set inside and outside 1`] = `
|
||||||
"function anonymous(context, extra
|
"function anonymous(context, extra
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1072,6 +1072,21 @@ describe("t-call (template calling", () => {
|
|||||||
expect(renderToString(qweb1, "main")).toBe("<div><span>ok</span></div>");
|
expect(renderToString(qweb1, "main")).toBe("<div><span>ok</span></div>");
|
||||||
expect(renderToString(qweb2, "main")).toBe("<div><span>ok</span></div>");
|
expect(renderToString(qweb2, "main")).toBe("<div><span>ok</span></div>");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("t-call with t-set inside and body text content", () => {
|
||||||
|
qweb.addTemplate("sub", `<p><t t-esc="val"/></p>`);
|
||||||
|
qweb.addTemplate(
|
||||||
|
"main",
|
||||||
|
`
|
||||||
|
<div>
|
||||||
|
<t t-call="sub">
|
||||||
|
<t t-set="val">yip yip</t>
|
||||||
|
</t>
|
||||||
|
</div>`
|
||||||
|
);
|
||||||
|
const expected = "<div><p>yip yip</p></div>";
|
||||||
|
expect(renderToString(qweb, "main")).toBe(expected);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("foreach", () => {
|
describe("foreach", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user