[FIX] qweb: t-foreach needs to hold on scope

Have a t-on within a t-foreach
the t-on has an expression

Before this commit, when triggering the t-on, the expression was falsely evaluated
In details, the expression took scope from outside the foreach loop
as we protect it to have similar results than an actual for loop

But, at triggering time, the scope protection had already been terminated
meaning the info of the iteration of the loop the handler has been built in
had already disappeared

This commit fixes that

closes #594
This commit is contained in:
Lucas Perais (lpe)
2020-01-06 17:01:43 +01:00
committed by Géry Debongnie
parent 21737d33fa
commit 21d1306ec2
6 changed files with 347 additions and 11 deletions
+109
View File
@@ -2902,6 +2902,115 @@ describe("other directives with t-component", () => {
await widget.mount(fixture);
expect(fixture.innerHTML).toBe("<div><p>InLoop: 0</p><p>InLoop: 1</p><p>EndLoop: 1</p></div>");
});
test("t-on expression in t-foreach", async () => {
class SomeWidget extends Component<any, any> {
static template = xml`
<div>
<div t-foreach="state.values" t-as="val" t-key="val">
<t t-esc="val_index"/>: <t t-esc="val + ''"/>
<button t-on-click="otherState.vals.push(val)">Expr</button>
</div>
</div>`;
state = useState({values: ['a', 'b']});
otherState = {vals: []};
}
const widget = new SomeWidget();
await widget.mount(fixture);
expect(fixture.innerHTML).toBe("<div><div>0: a<button>Expr</button></div><div>1: b<button>Expr</button></div></div>");
expect(widget.otherState.vals).toStrictEqual([]);
const buttons = fixture.querySelectorAll('button');
buttons[0].click();
buttons[1].click();
expect(widget.otherState.vals).toStrictEqual(['a', 'b']);
expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot();
});
test("t-on expression in t-foreach with t-set", async () => {
class SomeWidget extends Component<any, any> {
static template = xml`
<div>
<t t-set="bossa" t-value="'nova'"/>
<div t-foreach="state.values" t-as="val" t-key="val">
<t t-set="bossa" t-value="bossa + '_' + val_index" />
<t t-esc="val_index"/>: <t t-esc="val + ''"/>
<button t-on-click="otherState.vals.push(val + '_' + bossa)">Expr</button>
</div>
</div>`;
state = useState({values: ['a', 'b']});
otherState = {vals: []};
}
const widget = new SomeWidget();
await widget.mount(fixture);
expect(fixture.innerHTML).toBe("<div><div>0: a<button>Expr</button></div><div>1: b<button>Expr</button></div></div>");
expect(widget.otherState.vals).toStrictEqual([]);
const buttons = fixture.querySelectorAll('button');
buttons[0].click();
buttons[1].click();
expect(widget.otherState.vals).toStrictEqual(['a_nova_0', 'b_nova_0_1']);
expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot();
});
test("t-on method call in t-foreach", async () => {
class SomeWidget extends Component<any, any> {
static template = xml`
<div>
<div t-foreach="state.values" t-as="val" t-key="val">
<t t-esc="val_index"/>: <t t-esc="val + ''"/>
<button t-on-click="addVal(val)">meth call</button>
</div>
</div>`;
state = useState({values: ['a', 'b']});
otherState = {vals: new Array<string>()};
addVal(val: string) {
this.otherState.vals.push(val);
}
}
const widget = new SomeWidget();
await widget.mount(fixture);
expect(fixture.innerHTML).toBe("<div><div>0: a<button>meth call</button></div><div>1: b<button>meth call</button></div></div>");
expect(widget.otherState.vals).toStrictEqual([]);
const buttons = fixture.querySelectorAll('button');
buttons[0].click();
buttons[1].click();
expect(widget.otherState.vals).toStrictEqual(['a', 'b']);
expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot();
});
test("t-on expression captured in t-foreach", async () => {
class SomeWidget extends Component<any, any> {
static template = xml`
<div>
<t t-set="iter" t-value="0" />
<div t-foreach="arr" t-as="val" t-key="val">
<button t-on-click="otherState.vals.push(iter + '_' + iter)">expr</button>
<t t-set="iter" t-value="iter + 1" />
</div>
</div>`;
arr = ['a', 'b']
otherState = {vals: new Array<string>()};
}
const widget = new SomeWidget();
await widget.mount(fixture);
expect(fixture.innerHTML).toBe("<div><div><button>expr</button></div><div><button>expr</button></div></div>");
expect(widget.otherState.vals).toStrictEqual([]);
const buttons = fixture.querySelectorAll('button');
buttons[0].click();
buttons[1].click();
expect(widget.otherState.vals).toStrictEqual(['0_0', '1_1']);
expect(QWeb.TEMPLATES[SomeWidget.template].fn.toString()).toMatchSnapshot();
});
});
describe("random stuff/miscellaneous", () => {