mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] component: fix issues with component internal template key
closes #298
This commit is contained in:
+15
-17
@@ -243,21 +243,19 @@ QWeb.addDirective({
|
||||
ctx.addLine(`let key${keyID} = 'key' + ${key};`);
|
||||
}
|
||||
ctx.addLine(`let def${defID};`);
|
||||
let templateID = key
|
||||
? `key${keyID}`
|
||||
: ctx.inLoop
|
||||
? ctx.currentKey
|
||||
? `String(${ctx.currentKey} + '_k_' + i + '_c_' + ${componentID} )`
|
||||
: `String(-${componentID} - i)`
|
||||
: String(componentID);
|
||||
if (ctx.allowMultipleRoots) {
|
||||
templateID = `"_slot_${templateID}"`;
|
||||
|
||||
let locationExpr = `\`__${ctx.generateID()}__`;
|
||||
for (let i = 0; i < ctx.loopNumber - 1; i++) {
|
||||
locationExpr += `\${i${i + 1}}__`;
|
||||
}
|
||||
if (key || ctx.inLoop) {
|
||||
let id = ctx.generateID();
|
||||
ctx.addLine(`let templateId${id} = ${templateID};`);
|
||||
templateID = `templateId${id}`;
|
||||
if (key || ctx.currentKey) {
|
||||
const k = key ? `key${keyID}` : ctx.currentKey;
|
||||
ctx.addLine(`let templateId${componentID} = ${locationExpr}\` + ${k};`);
|
||||
} else {
|
||||
locationExpr += ctx.loopNumber ? `\${i${ctx.loopNumber}}__\`` : "`";
|
||||
ctx.addLine(`let templateId${componentID} = ${locationExpr};`);
|
||||
}
|
||||
const templateId = `templateId${componentID}`;
|
||||
|
||||
let ref = node.getAttribute("t-ref");
|
||||
let refExpr = "";
|
||||
@@ -320,7 +318,7 @@ QWeb.addDirective({
|
||||
.map(function([eventName, mods, handlerName, extraArgs]) {
|
||||
let params = "owner";
|
||||
if (extraArgs) {
|
||||
if (ctx.inLoop) {
|
||||
if (ctx.loopNumber) {
|
||||
let argId = ctx.generateID();
|
||||
// we need to evaluate the arguments now, because the handler will
|
||||
// be set asynchronously later when the widget is ready, and the
|
||||
@@ -352,7 +350,7 @@ QWeb.addDirective({
|
||||
}
|
||||
|
||||
ctx.addLine(
|
||||
`let w${componentID} = ${templateID} in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[${templateID}]] : false;`
|
||||
`let w${componentID} = ${templateId} in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[${templateId}]] : false;`
|
||||
);
|
||||
if (ctx.parentNode) {
|
||||
ctx.addLine(`let _${dummyID}_index = c${ctx.parentNode}.length;`);
|
||||
@@ -418,7 +416,7 @@ QWeb.addDirective({
|
||||
ctx.addLine(`utils.validateProps(W${componentID}, props${componentID})`);
|
||||
}
|
||||
ctx.addLine(`w${componentID} = new W${componentID}(parent, props${componentID});`);
|
||||
ctx.addLine(`parent.__owl__.cmap[${templateID}] = w${componentID}.__owl__.id;`);
|
||||
ctx.addLine(`parent.__owl__.cmap[${templateId}] = w${componentID}.__owl__.id;`);
|
||||
|
||||
// SLOTS
|
||||
const varDefs: string[] = [];
|
||||
@@ -470,7 +468,7 @@ QWeb.addDirective({
|
||||
registerCode = `utils.defineProxy(vn${ctx.rootNode}, pvnode);`;
|
||||
}
|
||||
ctx.addLine(
|
||||
`def${defID} = def${defID}.then(vnode=>{if (w${componentID}.__owl__.isDestroyed){return}${createHook}let pvnode=h(vnode.sel, {key: ${templateID}, hook: {insert(vn) {let nvn=w${componentID}.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;${refExpr}${transitionsInsertCode}},remove() {},destroy(vn) {${finalizeComponentCode}}}});${registerCode}w${componentID}.__owl__.pvnode = pvnode;});`
|
||||
`def${defID} = def${defID}.then(vnode=>{if (w${componentID}.__owl__.isDestroyed){return}${createHook}let pvnode=h(vnode.sel, {key: ${templateId}, hook: {insert(vn) {let nvn=w${componentID}.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;${refExpr}${transitionsInsertCode}},remove() {},destroy(vn) {${finalizeComponentCode}}}});${registerCode}w${componentID}.__owl__.pvnode = pvnode;});`
|
||||
);
|
||||
|
||||
ctx.addElse();
|
||||
|
||||
@@ -275,7 +275,7 @@ QWeb.addDirective({
|
||||
priority: 10,
|
||||
atNodeEncounter({ node, qweb, ctx }): boolean {
|
||||
ctx.rootContext.shouldProtectContext = true;
|
||||
ctx = ctx.subContext("inLoop", true);
|
||||
ctx = ctx.subContext("loopNumber", ctx.loopNumber + 1);
|
||||
const elems = node.getAttribute("t-foreach")!;
|
||||
const name = node.getAttribute("t-as")!;
|
||||
let arrayID = ctx.generateID();
|
||||
@@ -289,13 +289,14 @@ QWeb.addDirective({
|
||||
ctx.addLine(`_${valuesID} = Object.values(_${arrayID});`);
|
||||
ctx.closeIf();
|
||||
ctx.addLine(`var _length${keysID} = _${keysID}.length;`);
|
||||
ctx.addLine(`for (let i = 0; i < _length${keysID}; i++) {`);
|
||||
const loopVar = `i${ctx.loopNumber}`;
|
||||
ctx.addLine(`for (let ${loopVar} = 0; ${loopVar} < _length${keysID}; ${loopVar}++) {`);
|
||||
ctx.indent();
|
||||
ctx.addToScope(name + "_first", "i === 0");
|
||||
ctx.addToScope(name + "_last", `i === _length${keysID} - 1`);
|
||||
ctx.addToScope(name + "_index", "i");
|
||||
ctx.addToScope(name, `_${keysID}[i]`);
|
||||
ctx.addToScope(name + "_value", `_${valuesID}[i]`);
|
||||
ctx.addToScope(name + "_first", `${loopVar} === 0`);
|
||||
ctx.addToScope(name + "_last", `${loopVar} === _length${keysID} - 1`);
|
||||
ctx.addToScope(name + "_index", loopVar);
|
||||
ctx.addToScope(name, `_${keysID}[${loopVar}]`);
|
||||
ctx.addToScope(name + "_value", `_${valuesID}[${loopVar}]`);
|
||||
const nodeCopy = <Element>node.cloneNode(true);
|
||||
let shouldWarn = nodeCopy.tagName !== "t" && !nodeCopy.hasAttribute("t-key");
|
||||
if (!shouldWarn && node.tagName === "t") {
|
||||
|
||||
@@ -24,7 +24,7 @@ export class CompilationContext {
|
||||
shouldDefineResult: boolean = true;
|
||||
shouldProtectContext: boolean = false;
|
||||
shouldTrackScope: boolean = false;
|
||||
inLoop: boolean = false;
|
||||
loopNumber: number = 0;
|
||||
inPreTag: boolean = false;
|
||||
templateName: string;
|
||||
allowMultipleRoots: boolean = false;
|
||||
|
||||
@@ -12,7 +12,8 @@ exports[`animations t-transition combined with component 1`] = `
|
||||
var vn1 = h('div', p1, c1);
|
||||
//COMPONENT
|
||||
let def3;
|
||||
let w4 = 4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[4]] : false;
|
||||
let templateId4 = \`__5__\`;
|
||||
let w4 = templateId4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId4]] : false;
|
||||
let _2_index = c1.length;
|
||||
c1.push(null);
|
||||
let props4 = {};
|
||||
@@ -29,9 +30,9 @@ exports[`animations t-transition combined with component 1`] = `
|
||||
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| context['Child'];
|
||||
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||
w4 = new W4(parent, props4);
|
||||
parent.__owl__.cmap[4] = w4.__owl__.id;
|
||||
parent.__owl__.cmap[templateId4] = w4.__owl__.id;
|
||||
def3 = w4.__prepare(extra.fiber, undefined, undefined);
|
||||
def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;utils.transitionInsert(vn, 'chimay');},remove() {},destroy(vn) {let finalize = () => {
|
||||
def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;utils.transitionInsert(vn, 'chimay');},remove() {},destroy(vn) {let finalize = () => {
|
||||
w4.destroy();
|
||||
};
|
||||
utils.transitionRemove(vn, 'chimay', finalize);}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
|
||||
@@ -57,7 +58,8 @@ exports[`animations t-transition combined with t-component and t-if 1`] = `
|
||||
if (context['state'].display) {
|
||||
//COMPONENT
|
||||
let def3;
|
||||
let w4 = 4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[4]] : false;
|
||||
let templateId4 = \`__5__\`;
|
||||
let w4 = templateId4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId4]] : false;
|
||||
let _2_index = c1.length;
|
||||
c1.push(null);
|
||||
let props4 = {};
|
||||
@@ -74,9 +76,9 @@ exports[`animations t-transition combined with t-component and t-if 1`] = `
|
||||
let W4 = context.constructor.components[componentKey4] || QWeb.components[componentKey4]|| context['Child'];
|
||||
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||
w4 = new W4(parent, props4);
|
||||
parent.__owl__.cmap[4] = w4.__owl__.id;
|
||||
parent.__owl__.cmap[templateId4] = w4.__owl__.id;
|
||||
def3 = w4.__prepare(extra.fiber, undefined, undefined);
|
||||
def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;utils.transitionInsert(vn, 'chimay');},remove() {},destroy(vn) {let finalize = () => {
|
||||
def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;utils.transitionInsert(vn, 'chimay');},remove() {},destroy(vn) {let finalize = () => {
|
||||
w4.destroy();
|
||||
};
|
||||
utils.transitionRemove(vn, 'chimay', finalize);}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
|
||||
|
||||
@@ -251,11 +251,11 @@ describe("animations", () => {
|
||||
widget.state.display = false;
|
||||
patchNextFrame(cb => {
|
||||
expect(fixture.innerHTML).toBe(
|
||||
'<div><span class="chimay-leave chimay-leave-active" data-owl-key="4">blue</span></div>'
|
||||
'<div><span class="chimay-leave chimay-leave-active" data-owl-key="__5__">blue</span></div>'
|
||||
);
|
||||
cb();
|
||||
expect(fixture.innerHTML).toBe(
|
||||
'<div><span class="chimay-leave-active chimay-leave-to" data-owl-key="4">blue</span></div>'
|
||||
'<div><span class="chimay-leave-active chimay-leave-to" data-owl-key="__5__">blue</span></div>'
|
||||
);
|
||||
def.resolve();
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,8 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] =
|
||||
var vn1 = h('div', p1, c1);
|
||||
//COMPONENT
|
||||
let def3;
|
||||
let w4 = 4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[4]] : false;
|
||||
let templateId4 = \`__5__\`;
|
||||
let w4 = templateId4 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId4]] : false;
|
||||
let _2_index = c1.length;
|
||||
c1.push(null);
|
||||
let props4 = {message:1};
|
||||
@@ -34,9 +35,9 @@ exports[`props validation props are validated in dev mode (code snapshot) 1`] =
|
||||
if (!W4) {throw new Error('Cannot find the definition of component \\"' + componentKey4 + '\\"')}
|
||||
utils.validateProps(W4, props4)
|
||||
w4 = new W4(parent, props4);
|
||||
parent.__owl__.cmap[4] = w4.__owl__.id;
|
||||
parent.__owl__.cmap[templateId4] = w4.__owl__.id;
|
||||
def3 = w4.__prepare(extra.fiber, undefined, undefined);
|
||||
def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: 4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
|
||||
def3 = def3.then(vnode=>{if (w4.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId4, hook: {insert(vn) {let nvn=w4.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});c1[_2_index]=pvnode;w4.__owl__.pvnode = pvnode;});
|
||||
} else {
|
||||
utils.validateProps(w4.constructor, props4)
|
||||
def3 = def3 || w4.__updateProps(props4, extra.fiber, undefined, undefined);
|
||||
|
||||
@@ -182,6 +182,52 @@ describe("basic widget properties", () => {
|
||||
await widget.mount(fixture);
|
||||
expect(fixture.innerHTML).toBe("<div><span>child</span><span>child</span></div>");
|
||||
});
|
||||
|
||||
test("reconciliation alg works for t-foreach in t-foreach", async () => {
|
||||
const warn = console.warn;
|
||||
console.warn = () => {};
|
||||
class Child extends Component<any, any> {
|
||||
static template = xml`<div><t t-esc="props.blip"/></div>`;
|
||||
}
|
||||
|
||||
class Parent extends Component<any, any> {
|
||||
static template = xml`
|
||||
<div>
|
||||
<t t-foreach="state.s" t-as="section">
|
||||
<t t-foreach="section.blips" t-as="blip">
|
||||
<Child blip="blip"/>
|
||||
</t>
|
||||
</t>
|
||||
</div>`;
|
||||
static components = { Child };
|
||||
state = { s: [{ blips: ["a1", "a2"] }, { blips: ["b1"] }] };
|
||||
}
|
||||
|
||||
const widget = new Parent(env);
|
||||
await widget.mount(fixture);
|
||||
expect(fixture.innerHTML).toBe("<div><div>a1</div><div>a2</div><div>b1</div></div>");
|
||||
expect(env.qweb.templates[Parent.template].fn.toString()).toMatchSnapshot();
|
||||
console.warn = warn;
|
||||
});
|
||||
|
||||
test("same t-keys in two different places", async () => {
|
||||
class Child extends Component<any, any> {
|
||||
static template = xml`<span><t t-esc="props.blip"/></span>`;
|
||||
}
|
||||
|
||||
class Parent extends Component<any, any> {
|
||||
static template = xml`
|
||||
<div>
|
||||
<div><Child t-key="1" blip="'1'"/></div>
|
||||
<div><Child t-key="1" blip="'2'"/></div>
|
||||
</div>`;
|
||||
static components = { Child };
|
||||
}
|
||||
|
||||
const widget = new Parent(env);
|
||||
await widget.mount(fixture);
|
||||
expect(fixture.innerHTML).toBe("<div><div><span>1</span></div><div><span>2</span></div></div>");
|
||||
});
|
||||
});
|
||||
|
||||
describe("lifecycle hooks", () => {
|
||||
|
||||
@@ -325,12 +325,12 @@ exports[`foreach does not pollute the rendering context 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.item_first = i === 0;
|
||||
context.item_last = i === _length3 - 1;
|
||||
context.item_index = i;
|
||||
context.item = _3[i];
|
||||
context.item_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.item_first = i1 === 0;
|
||||
context.item_last = i1 === _length3 - 1;
|
||||
context.item_index = i1;
|
||||
context.item = _3[i1];
|
||||
context.item_value = _4[i1];
|
||||
var _5 = context['item'];
|
||||
if (_5 || _5 === 0) {
|
||||
c1.push({text: _5});
|
||||
@@ -355,12 +355,12 @@ exports[`foreach iterate on items (on a element node) 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.item_first = i === 0;
|
||||
context.item_last = i === _length3 - 1;
|
||||
context.item_index = i;
|
||||
context.item = _3[i];
|
||||
context.item_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.item_first = i1 === 0;
|
||||
context.item_last = i1 === _length3 - 1;
|
||||
context.item_index = i1;
|
||||
context.item = _3[i1];
|
||||
context.item_value = _4[i1];
|
||||
const nodeKey5 = context['item']
|
||||
let c5 = [], p5 = {key:nodeKey5};
|
||||
var vn5 = h('span', p5, c5);
|
||||
@@ -389,12 +389,12 @@ exports[`foreach iterate on items 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.item_first = i === 0;
|
||||
context.item_last = i === _length3 - 1;
|
||||
context.item_index = i;
|
||||
context.item = _3[i];
|
||||
context.item_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.item_first = i1 === 0;
|
||||
context.item_last = i1 === _length3 - 1;
|
||||
context.item_index = i1;
|
||||
context.item = _3[i1];
|
||||
context.item_value = _4[i1];
|
||||
c1.push({text: \` [\`});
|
||||
var _5 = context['item_index'];
|
||||
if (_5 || _5 === 0) {
|
||||
@@ -431,12 +431,12 @@ exports[`foreach iterate, dict param 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.item_first = i === 0;
|
||||
context.item_last = i === _length3 - 1;
|
||||
context.item_index = i;
|
||||
context.item = _3[i];
|
||||
context.item_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.item_first = i1 === 0;
|
||||
context.item_last = i1 === _length3 - 1;
|
||||
context.item_index = i1;
|
||||
context.item = _3[i1];
|
||||
context.item_value = _4[i1];
|
||||
c1.push({text: \` [\`});
|
||||
var _5 = context['item_index'];
|
||||
if (_5 || _5 === 0) {
|
||||
@@ -473,12 +473,12 @@ exports[`foreach iterate, position 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.elem_first = i === 0;
|
||||
context.elem_last = i === _length3 - 1;
|
||||
context.elem_index = i;
|
||||
context.elem = _3[i];
|
||||
context.elem_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.elem_first = i1 === 0;
|
||||
context.elem_last = i1 === _length3 - 1;
|
||||
context.elem_index = i1;
|
||||
context.elem = _3[i1];
|
||||
context.elem_value = _4[i1];
|
||||
c1.push({text: \` -\`});
|
||||
if (context['elem_first']) {
|
||||
c1.push({text: \` first\`});
|
||||
@@ -497,6 +497,57 @@ exports[`foreach iterate, position 1`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`foreach t-foreach in t-forach 1`] = `
|
||||
"function anonymous(context,extra
|
||||
) {
|
||||
context = Object.create(context);
|
||||
var h = this.h;
|
||||
let c1 = [], p1 = {key:1};
|
||||
var vn1 = h('div', p1, c1);
|
||||
var _2 = context['numbers'];
|
||||
if (!_2) { throw new Error('QWeb error: Invalid loop expression')}
|
||||
var _3 = _4 = _2;
|
||||
if (!(_2 instanceof Array)) {
|
||||
_3 = Object.keys(_2);
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.number_first = i1 === 0;
|
||||
context.number_last = i1 === _length3 - 1;
|
||||
context.number_index = i1;
|
||||
context.number = _3[i1];
|
||||
context.number_value = _4[i1];
|
||||
var _5 = context['letters'];
|
||||
if (!_5) { throw new Error('QWeb error: Invalid loop expression')}
|
||||
var _6 = _7 = _5;
|
||||
if (!(_5 instanceof Array)) {
|
||||
_6 = Object.keys(_5);
|
||||
_7 = Object.values(_5);
|
||||
}
|
||||
var _length6 = _6.length;
|
||||
for (let i2 = 0; i2 < _length6; i2++) {
|
||||
context.letter_first = i2 === 0;
|
||||
context.letter_last = i2 === _length6 - 1;
|
||||
context.letter_index = i2;
|
||||
context.letter = _6[i2];
|
||||
context.letter_value = _7[i2];
|
||||
c1.push({text: \` [\`});
|
||||
var _8 = context['number'];
|
||||
if (_8 || _8 === 0) {
|
||||
c1.push({text: _8});
|
||||
}
|
||||
var _9 = context['letter'];
|
||||
if (_9 || _9 === 0) {
|
||||
c1.push({text: _9});
|
||||
}
|
||||
c1.push({text: \`] \`});
|
||||
}
|
||||
}
|
||||
return vn1;
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`foreach warn if no key in some case 1`] = `
|
||||
"function anonymous(context,extra
|
||||
) {
|
||||
@@ -512,12 +563,12 @@ exports[`foreach warn if no key in some case 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.item_first = i === 0;
|
||||
context.item_last = i === _length3 - 1;
|
||||
context.item_index = i;
|
||||
context.item = _3[i];
|
||||
context.item_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.item_first = i1 === 0;
|
||||
context.item_last = i1 === _length3 - 1;
|
||||
context.item_index = i1;
|
||||
context.item = _3[i1];
|
||||
context.item_value = _4[i1];
|
||||
let c5 = [], p5 = {key:5};
|
||||
var vn5 = h('span', p5, c5);
|
||||
c1.push(vn5);
|
||||
@@ -575,12 +626,12 @@ exports[`misc global 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.value_first = i === 0;
|
||||
context.value_last = i === _length3 - 1;
|
||||
context.value_index = i;
|
||||
context.value = _3[i];
|
||||
context.value_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.value_first = i1 === 0;
|
||||
context.value_last = i1 === _length3 - 1;
|
||||
context.value_index = i1;
|
||||
context.value = _3[i1];
|
||||
context.value_value = _4[i1];
|
||||
let c5 = [], p5 = {key:5};
|
||||
var vn5 = h('span', p5, c5);
|
||||
c1.push(vn5);
|
||||
@@ -940,16 +991,16 @@ exports[`t-call (template calling recursive template, part 2 1`] = `
|
||||
_8 = Object.values(_6);
|
||||
}
|
||||
var _length7 = _7.length;
|
||||
for (let i = 0; i < _length7; i++) {
|
||||
context.subtree_first = i === 0;
|
||||
for (let i1 = 0; i1 < _length7; i1++) {
|
||||
context.subtree_first = i1 === 0;
|
||||
scope.subtree_first = context.subtree_first;
|
||||
context.subtree_last = i === _length7 - 1;
|
||||
context.subtree_last = i1 === _length7 - 1;
|
||||
scope.subtree_last = context.subtree_last;
|
||||
context.subtree_index = i;
|
||||
context.subtree_index = i1;
|
||||
scope.subtree_index = context.subtree_index;
|
||||
context.subtree = _7[i];
|
||||
context.subtree = _7[i1];
|
||||
scope.subtree = context.subtree;
|
||||
context.subtree_value = _8[i];
|
||||
context.subtree_value = _8[i1];
|
||||
scope.subtree_value = context.subtree_value;
|
||||
this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c3, fiber: {vars: {_v0: context['subtree']}, scope}}));
|
||||
}
|
||||
@@ -986,16 +1037,16 @@ exports[`t-call (template calling recursive template, part 2 2`] = `
|
||||
_17 = Object.values(_15);
|
||||
}
|
||||
var _length16 = _16.length;
|
||||
for (let i = 0; i < _length16; i++) {
|
||||
context.subtree_first = i === 0;
|
||||
for (let i1 = 0; i1 < _length16; i1++) {
|
||||
context.subtree_first = i1 === 0;
|
||||
scope.subtree_first = context.subtree_first;
|
||||
context.subtree_last = i === _length16 - 1;
|
||||
context.subtree_last = i1 === _length16 - 1;
|
||||
scope.subtree_last = context.subtree_last;
|
||||
context.subtree_index = i;
|
||||
context.subtree_index = i1;
|
||||
scope.subtree_index = context.subtree_index;
|
||||
context.subtree = _16[i];
|
||||
context.subtree = _16[i1];
|
||||
scope.subtree = context.subtree;
|
||||
context.subtree_value = _17[i];
|
||||
context.subtree_value = _17[i1];
|
||||
scope.subtree_value = context.subtree_value;
|
||||
this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c12, fiber: {vars: {_v0: context['subtree']}, scope}}));
|
||||
}
|
||||
@@ -1031,16 +1082,16 @@ exports[`t-call (template calling recursive template, part 3 1`] = `
|
||||
_8 = Object.values(_6);
|
||||
}
|
||||
var _length7 = _7.length;
|
||||
for (let i = 0; i < _length7; i++) {
|
||||
context.subtree_first = i === 0;
|
||||
for (let i1 = 0; i1 < _length7; i1++) {
|
||||
context.subtree_first = i1 === 0;
|
||||
scope.subtree_first = context.subtree_first;
|
||||
context.subtree_last = i === _length7 - 1;
|
||||
context.subtree_last = i1 === _length7 - 1;
|
||||
scope.subtree_last = context.subtree_last;
|
||||
context.subtree_index = i;
|
||||
context.subtree_index = i1;
|
||||
scope.subtree_index = context.subtree_index;
|
||||
context.subtree = _7[i];
|
||||
context.subtree = _7[i1];
|
||||
scope.subtree = context.subtree;
|
||||
context.subtree_value = _8[i];
|
||||
context.subtree_value = _8[i1];
|
||||
scope.subtree_value = context.subtree_value;
|
||||
this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c3, fiber: {vars: {_v0: context['subtree']}, scope}}));
|
||||
}
|
||||
@@ -1077,16 +1128,16 @@ exports[`t-call (template calling recursive template, part 3 2`] = `
|
||||
_17 = Object.values(_15);
|
||||
}
|
||||
var _length16 = _16.length;
|
||||
for (let i = 0; i < _length16; i++) {
|
||||
context.subtree_first = i === 0;
|
||||
for (let i1 = 0; i1 < _length16; i1++) {
|
||||
context.subtree_first = i1 === 0;
|
||||
scope.subtree_first = context.subtree_first;
|
||||
context.subtree_last = i === _length16 - 1;
|
||||
context.subtree_last = i1 === _length16 - 1;
|
||||
scope.subtree_last = context.subtree_last;
|
||||
context.subtree_index = i;
|
||||
context.subtree_index = i1;
|
||||
scope.subtree_index = context.subtree_index;
|
||||
context.subtree = _16[i];
|
||||
context.subtree = _16[i1];
|
||||
scope.subtree = context.subtree;
|
||||
context.subtree_value = _17[i];
|
||||
context.subtree_value = _17[i1];
|
||||
scope.subtree_value = context.subtree_value;
|
||||
this.recursiveFns['__10'].call(this, context, Object.assign({}, extra, {parentNode: c12, fiber: {vars: {_v0: context['subtree']}, scope}}));
|
||||
}
|
||||
@@ -1446,12 +1497,12 @@ exports[`t-key t-key directive in a list 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.beer_first = i === 0;
|
||||
context.beer_last = i === _length3 - 1;
|
||||
context.beer_index = i;
|
||||
context.beer = _3[i];
|
||||
context.beer_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.beer_first = i1 === 0;
|
||||
context.beer_last = i1 === _length3 - 1;
|
||||
context.beer_index = i1;
|
||||
context.beer = _3[i1];
|
||||
context.beer_value = _4[i1];
|
||||
const nodeKey5 = context['beer'].id
|
||||
let c5 = [], p5 = {key:nodeKey5};
|
||||
var vn5 = h('li', p5, c5);
|
||||
@@ -1548,12 +1599,12 @@ exports[`t-on can bind handlers with loop variable as argument 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.action_first = i === 0;
|
||||
context.action_last = i === _length3 - 1;
|
||||
context.action_index = i;
|
||||
context.action = _3[i];
|
||||
context.action_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.action_first = i1 === 0;
|
||||
context.action_last = i1 === _length3 - 1;
|
||||
context.action_index = i1;
|
||||
context.action = _3[i1];
|
||||
context.action_value = _4[i1];
|
||||
const nodeKey5 = context['action_index']
|
||||
let c5 = [], p5 = {key:nodeKey5};
|
||||
var vn5 = h('li', p5, c5);
|
||||
@@ -1750,12 +1801,12 @@ exports[`t-on t-on with prevent modifier in t-foreach 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.project_first = i === 0;
|
||||
context.project_last = i === _length3 - 1;
|
||||
context.project_index = i;
|
||||
context.project = _3[i];
|
||||
context.project_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.project_first = i1 === 0;
|
||||
context.project_last = i1 === _length3 - 1;
|
||||
context.project_index = i1;
|
||||
context.project = _3[i1];
|
||||
context.project_value = _4[i1];
|
||||
var _5 = '#';
|
||||
const nodeKey6 = context['project']
|
||||
let c6 = [], p6 = {key:nodeKey6,attrs:{href: _5},on:{}};
|
||||
@@ -1960,12 +2011,12 @@ exports[`t-ref refs in a loop 1`] = `
|
||||
_4 = Object.values(_2);
|
||||
}
|
||||
var _length3 = _3.length;
|
||||
for (let i = 0; i < _length3; i++) {
|
||||
context.item_first = i === 0;
|
||||
context.item_last = i === _length3 - 1;
|
||||
context.item_index = i;
|
||||
context.item = _3[i];
|
||||
context.item_value = _4[i];
|
||||
for (let i1 = 0; i1 < _length3; i1++) {
|
||||
context.item_first = i1 === 0;
|
||||
context.item_last = i1 === _length3 - 1;
|
||||
context.item_index = i1;
|
||||
context.item = _3[i1];
|
||||
context.item_value = _4[i1];
|
||||
const nodeKey5 = context['item']
|
||||
let c5 = [], p5 = {key:nodeKey5};
|
||||
var vn5 = h('div', p5, c5);
|
||||
@@ -2126,12 +2177,12 @@ exports[`t-set t-set should reuse variable if possible 1`] = `
|
||||
_5 = Object.values(_3);
|
||||
}
|
||||
var _length4 = _4.length;
|
||||
for (let i = 0; i < _length4; i++) {
|
||||
context.elem_first = i === 0;
|
||||
context.elem_last = i === _length4 - 1;
|
||||
context.elem_index = i;
|
||||
context.elem = _4[i];
|
||||
context.elem_value = _5[i];
|
||||
for (let i1 = 0; i1 < _length4; i1++) {
|
||||
context.elem_first = i1 === 0;
|
||||
context.elem_last = i1 === _length4 - 1;
|
||||
context.elem_index = i1;
|
||||
context.elem = _4[i1];
|
||||
context.elem_value = _5[i1];
|
||||
const nodeKey6 = context['elem_index']
|
||||
let c6 = [], p6 = {key:nodeKey6};
|
||||
var vn6 = h('div', p6, c6);
|
||||
|
||||
@@ -749,6 +749,23 @@ describe("foreach", () => {
|
||||
expect(Object.keys(context).length).toBe(0);
|
||||
});
|
||||
|
||||
test("t-foreach in t-forach", () => {
|
||||
qweb.addTemplate(
|
||||
"test",
|
||||
`<div>
|
||||
<t t-foreach="numbers" t-as="number">
|
||||
<t t-foreach="letters" t-as="letter">
|
||||
[<t t-esc="number"/><t t-esc="letter"/>]
|
||||
</t>
|
||||
</t>
|
||||
</div>`
|
||||
);
|
||||
const context = { numbers: [1, 2, 3], letters: ["a", "b"] };
|
||||
expect(renderToString(qweb, "test", context)).toBe(
|
||||
"<div> [1a] [1b] [2a] [2b] [3a] [3b] </div>"
|
||||
);
|
||||
});
|
||||
|
||||
test("throws error if invalid loop expression", () => {
|
||||
qweb.addTemplate(
|
||||
"test",
|
||||
|
||||
@@ -13,8 +13,8 @@ exports[`RouteComponent can render simple cases 1`] = `
|
||||
//COMPONENT
|
||||
let key4 = 'key' + context['env'].router.currentRouteName;
|
||||
let def2;
|
||||
let templateId5 = key4;
|
||||
let w3 = templateId5 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId5]] : false;
|
||||
let templateId3 = \`__5__\` + key4;
|
||||
let w3 = templateId3 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[templateId3]] : false;
|
||||
let vn6 = {};
|
||||
result = vn6;
|
||||
let props3 = Object.assign({}, context['env'].router.currentParams);
|
||||
@@ -31,9 +31,9 @@ exports[`RouteComponent can render simple cases 1`] = `
|
||||
let W3 = context.constructor.components[componentKey3] || QWeb.components[componentKey3]|| context['routeComponent'];
|
||||
if (!W3) {throw new Error('Cannot find the definition of component \\"' + componentKey3 + '\\"')}
|
||||
w3 = new W3(parent, props3);
|
||||
parent.__owl__.cmap[templateId5] = w3.__owl__.id;
|
||||
parent.__owl__.cmap[templateId3] = w3.__owl__.id;
|
||||
def2 = w3.__prepare(extra.fiber, undefined, undefined);
|
||||
def2 = def2.then(vnode=>{if (w3.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId5, hook: {insert(vn) {let nvn=w3.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}});utils.defineProxy(vn6, pvnode);w3.__owl__.pvnode = pvnode;});
|
||||
def2 = def2.then(vnode=>{if (w3.__owl__.isDestroyed){return}let pvnode=h(vnode.sel, {key: templateId3, hook: {insert(vn) {let nvn=w3.__mount(vnode, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w3.destroy();}}});utils.defineProxy(vn6, pvnode);w3.__owl__.pvnode = pvnode;});
|
||||
} else {
|
||||
def2 = def2 || w3.__updateProps(props3, extra.fiber, undefined, undefined);
|
||||
def2 = def2.then(()=>{if (w3.__owl__.isDestroyed) {return};let pvnode=w3.__owl__.pvnode;utils.defineProxy(vn6, pvnode);});
|
||||
|
||||
Reference in New Issue
Block a user