mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] qweb: scope t-key directive to node and subnodes
not to siblings closes #503
This commit is contained in:
@@ -32,7 +32,6 @@ export class CompilationContext {
|
||||
hasParentWidget: boolean = false;
|
||||
scopeVars: any[] = [];
|
||||
currentKey: string = "";
|
||||
lastNodeKey: string = ""; // temp variable to communicate to previous caller
|
||||
templates: { [key: string]: boolean } = {};
|
||||
|
||||
constructor(name?: string) {
|
||||
@@ -61,8 +60,8 @@ export class CompilationContext {
|
||||
for (let i = 0; i < this.loopNumber - 1; i++) {
|
||||
locationExpr += `\${i${i + 1}}__`;
|
||||
}
|
||||
if (this.lastNodeKey || this.currentKey) {
|
||||
const k = this.lastNodeKey || this.currentKey;
|
||||
if (this.currentKey) {
|
||||
const k = this.currentKey;
|
||||
this.addLine(`let k${id} = ${locationExpr}\` + ${k};`);
|
||||
} else {
|
||||
locationExpr += this.loopNumber ? `\${i${this.loopNumber}}__\`` : "`";
|
||||
|
||||
@@ -279,6 +279,6 @@ QWeb.addDirective({
|
||||
atNodeEncounter({ ctx, value }) {
|
||||
let id = ctx.generateID();
|
||||
ctx.addLine(`const nodeKey${id} = ${ctx.formatExpression(value)};`);
|
||||
ctx.lastNodeKey = `nodeKey${id}`;
|
||||
ctx.currentKey = `nodeKey${id}`;
|
||||
}
|
||||
});
|
||||
|
||||
+5
-2
@@ -455,6 +455,10 @@ export class QWeb extends EventBus {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx !== ctx.rootContext) {
|
||||
ctx = ctx.subContext("currentKey", ctx.currentKey);
|
||||
}
|
||||
|
||||
const firstLetter = node.tagName[0];
|
||||
if (firstLetter === firstLetter.toUpperCase()) {
|
||||
// this is a component, we modify in place the xml document to change
|
||||
@@ -544,7 +548,6 @@ export class QWeb extends EventBus {
|
||||
if (node.nodeName !== "t") {
|
||||
let nodeID = this._compileGenericNode(node, ctx, withHandlers);
|
||||
ctx = ctx.withParent(nodeID);
|
||||
ctx = ctx.subContext("currentKey", ctx.lastNodeKey);
|
||||
let nodeHooks = {};
|
||||
let addNodeHook = function(hook, handler) {
|
||||
nodeHooks[hook] = nodeHooks[hook] || [];
|
||||
@@ -728,7 +731,7 @@ export class QWeb extends EventBus {
|
||||
}
|
||||
}
|
||||
let nodeID = ctx.generateID();
|
||||
let nodeKey = ctx.lastNodeKey || nodeID;
|
||||
let nodeKey = ctx.currentKey || nodeID;
|
||||
const parts = [`key:${nodeKey}`];
|
||||
if (attrs.length + tattrs.length > 0) {
|
||||
parts.push(`attrs:{${attrs.join(",")}}`);
|
||||
|
||||
@@ -73,6 +73,78 @@ exports[`basic widget properties reconciliation alg works for t-foreach in t-for
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`basic widget properties t-key on a component with t-if, and a sibling component 1`] = `
|
||||
"function anonymous(context,extra
|
||||
) {
|
||||
let utils = this.constructor.utils;
|
||||
let QWeb = this.constructor;
|
||||
let parent = context;
|
||||
let owner = context;
|
||||
let sibling = null;
|
||||
var h = this.h;
|
||||
let c1 = [], p1 = {key:1};
|
||||
var vn1 = h('div', p1, c1);
|
||||
if (false) {
|
||||
const nodeKey2 = 'str';
|
||||
//COMPONENT
|
||||
let k5 = \`__6__\` + nodeKey2;
|
||||
let w4 = k5 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k5]] : false;
|
||||
let props4 = {};
|
||||
if (w4 && w4.__owl__.currentFiber && !w4.__owl__.vnode) {
|
||||
w4.destroy();
|
||||
w4 = false;
|
||||
}
|
||||
if (w4) {
|
||||
w4.__updateProps(props4, extra.fiber, undefined, undefined, sibling);
|
||||
let pvnode = w4.__owl__.pvnode;
|
||||
c1.push(pvnode);
|
||||
} else {
|
||||
let componentKey4 = \`Child\`;
|
||||
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[k5] = w4.__owl__.id;
|
||||
let def3 = w4.__prepare(extra.fiber, undefined, undefined, sibling);
|
||||
let pvnode = h('dummy', {key: k5, hook: {insert(vn) { let nvn=w4.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w4.destroy();}}});
|
||||
const fiber = w4.__owl__.currentFiber;
|
||||
def3.then(function () { if (fiber.isCompleted) { return; } const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
|
||||
c1.push(pvnode);
|
||||
w4.__owl__.pvnode = pvnode;
|
||||
}
|
||||
w4.__owl__.parentLastFiberId = extra.fiber.id;
|
||||
sibling = w4.__owl__.currentFiber || sibling;
|
||||
}
|
||||
//COMPONENT
|
||||
let k9 = \`__10__\`;
|
||||
let w8 = k9 in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[k9]] : false;
|
||||
let props8 = {};
|
||||
if (w8 && w8.__owl__.currentFiber && !w8.__owl__.vnode) {
|
||||
w8.destroy();
|
||||
w8 = false;
|
||||
}
|
||||
if (w8) {
|
||||
w8.__updateProps(props8, extra.fiber, undefined, undefined, sibling);
|
||||
let pvnode = w8.__owl__.pvnode;
|
||||
c1.push(pvnode);
|
||||
} else {
|
||||
let componentKey8 = \`Child\`;
|
||||
let W8 = context.constructor.components[componentKey8] || QWeb.components[componentKey8]|| context['Child'];
|
||||
if (!W8) {throw new Error('Cannot find the definition of component \\"' + componentKey8 + '\\"')}
|
||||
w8 = new W8(parent, props8);
|
||||
parent.__owl__.cmap[k9] = w8.__owl__.id;
|
||||
let def7 = w8.__prepare(extra.fiber, undefined, undefined, sibling);
|
||||
let pvnode = h('dummy', {key: k9, hook: {insert(vn) { let nvn=w8.__mount(fiber, pvnode.elm);pvnode.elm=nvn.elm;},remove() {},destroy(vn) {w8.destroy();}}});
|
||||
const fiber = w8.__owl__.currentFiber;
|
||||
def7.then(function () { if (fiber.isCompleted) { return; } const vnode = fiber.vnode; pvnode.sel = vnode.sel; });
|
||||
c1.push(pvnode);
|
||||
w8.__owl__.pvnode = pvnode;
|
||||
}
|
||||
w8.__owl__.parentLastFiberId = extra.fiber.id;
|
||||
sibling = w8.__owl__.currentFiber || sibling;
|
||||
return vn1;
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`class and style attributes with t-component dynamic t-att-style is properly added and updated on widget root el 1`] = `
|
||||
"function anonymous(context,extra
|
||||
) {
|
||||
|
||||
@@ -336,6 +336,26 @@ describe("basic widget properties", () => {
|
||||
await widget.mount(fixture);
|
||||
expect(fixture.innerHTML).toBe("<div><div><span>1</span></div><div><span>2</span></div></div>");
|
||||
});
|
||||
|
||||
test("t-key on a component with t-if, and a sibling component", async () => {
|
||||
class Child extends Component<any, any> {
|
||||
static template = xml`<span>child</span>`;
|
||||
}
|
||||
|
||||
class Parent extends Component<any, any> {
|
||||
static template = xml`
|
||||
<div>
|
||||
<Child t-if="false" t-key="'str'"/>
|
||||
<Child/>
|
||||
</div>`;
|
||||
static components = { Child };
|
||||
}
|
||||
|
||||
const widget = new Parent();
|
||||
await widget.mount(fixture);
|
||||
expect(fixture.innerHTML).toBe("<div><span>child</span></div>");
|
||||
expect(env.qweb.templates[Parent.template].fn.toString()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("lifecycle hooks", () => {
|
||||
|
||||
@@ -1592,12 +1592,12 @@ exports[`t-if t-set, then t-elif, part 3 1`] = `
|
||||
c1.push(vn4);
|
||||
c4.push({text: \`AAA\`});
|
||||
}
|
||||
else if (!_3) {
|
||||
let c5 = [], p5 = {key:5};
|
||||
var vn5 = h('span', p5, c5);
|
||||
c1.push(vn5);
|
||||
c5.push({text: \`BBB\`});
|
||||
}
|
||||
else if (!_3) {
|
||||
let c5 = [], p5 = {key:5};
|
||||
var vn5 = h('span', p5, c5);
|
||||
c1.push(vn5);
|
||||
c5.push({text: \`BBB\`});
|
||||
}
|
||||
return vn1;
|
||||
}"
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user