mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] qweb: accept assignations in qweb expressions
closes #560 closes #569
This commit is contained in:
@@ -81,7 +81,7 @@ const STATIC_TOKEN_MAP: { [key: string]: TKind } = {
|
||||
|
||||
// note that the space after typeof is relevant. It makes sure that the formatted
|
||||
// expression has a space after typeof
|
||||
const OPERATORS = ".,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>".split(",");
|
||||
const OPERATORS = ".,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=".split(",");
|
||||
|
||||
type Tokenizer = (expr: string) => Token | false;
|
||||
|
||||
|
||||
@@ -2026,6 +2026,24 @@ describe("other directives with t-component", () => {
|
||||
expect(flag).toBe(true);
|
||||
});
|
||||
|
||||
test("t-on with inline statement", 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-on-click="state.n = state.n + 1"/></div>`;
|
||||
static components = { Child };
|
||||
state = {n: 3};
|
||||
}
|
||||
const parent = new Parent();
|
||||
await parent.mount(fixture);
|
||||
expect(parent.state.n).toBe(3);
|
||||
fixture.querySelector("span")!.click();
|
||||
expect(parent.state.n).toBe(4);
|
||||
});
|
||||
|
||||
|
||||
test("t-on with handler bound to argument", async () => {
|
||||
expect.assertions(3);
|
||||
env.qweb.addTemplates(`
|
||||
|
||||
@@ -2308,6 +2308,34 @@ exports[`t-on t-on with inline statement 1`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-on t-on with inline statement, part 2 1`] = `
|
||||
"function anonymous(context, extra
|
||||
) {
|
||||
// Template name: \\"test\\"
|
||||
let scope = Object.create(context);
|
||||
var h = this.h;
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
p1.on['click'] = function (e) {if (!context.__owl__.isMounted){return}scope['state'].flag=!scope['state'].flag};
|
||||
c1.push({text: \`Toggle\`});
|
||||
return vn1;
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-on t-on with inline statement, part 3 1`] = `
|
||||
"function anonymous(context, extra
|
||||
) {
|
||||
// Template name: \\"test\\"
|
||||
let scope = Object.create(context);
|
||||
var h = this.h;
|
||||
let c1 = [], p1 = {key:1,on:{}};
|
||||
var vn1 = h('button', p1, c1);
|
||||
p1.on['click'] = function (e) {if (!context.__owl__.isMounted){return}scope['state'].n=scope['someFunction'](3)};
|
||||
c1.push({text: \`Toggle\`});
|
||||
return vn1;
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`t-on t-on with prevent and self modifiers (order matters) 1`] = `
|
||||
"function anonymous(context, extra
|
||||
) {
|
||||
|
||||
@@ -1293,6 +1293,37 @@ describe.only("t-on", () => {
|
||||
expect(owner.state.counter).toBe(2);
|
||||
});
|
||||
|
||||
test("t-on with inline statement, part 2", () => {
|
||||
qweb.addTemplate("test", `<button t-on-click="state.flag = !state.flag">Toggle</button>`);
|
||||
let owner = {
|
||||
state: {
|
||||
flag: true
|
||||
}
|
||||
};
|
||||
const node = renderToDOM(qweb, "test", owner, { handlers: [] });
|
||||
expect(owner.state.flag).toBe(true);
|
||||
(<HTMLElement>node).click();
|
||||
expect(owner.state.flag).toBe(false);
|
||||
(<HTMLElement>node).click();
|
||||
expect(owner.state.flag).toBe(true);
|
||||
});
|
||||
|
||||
test("t-on with inline statement, part 3", () => {
|
||||
qweb.addTemplate("test", `<button t-on-click="state.n = someFunction(3)">Toggle</button>`);
|
||||
let owner = {
|
||||
someFunction(n) {
|
||||
return n + 1;
|
||||
},
|
||||
state: {
|
||||
n: 11
|
||||
}
|
||||
};
|
||||
const node = renderToDOM(qweb, "test", owner, { handlers: [] });
|
||||
expect(owner.state.n).toBe(11);
|
||||
(<HTMLElement>node).click();
|
||||
expect(owner.state.n).toBe(4);
|
||||
});
|
||||
|
||||
test("t-on with prevent and/or stop modifiers", async () => {
|
||||
expect.assertions(7);
|
||||
qweb.addTemplate(
|
||||
|
||||
@@ -170,4 +170,11 @@ describe("expression evaluation", () => {
|
||||
"scope['list'].map((elem,index)=>elem+index)"
|
||||
);
|
||||
});
|
||||
|
||||
test("assignation", () => {
|
||||
expect(compileExpr("a = b", {})).toBe("scope['a']=scope['b']");
|
||||
expect(compileExpr("a += b", {})).toBe("scope['a']+=scope['b']");
|
||||
expect(compileExpr("a -= b", {})).toBe("scope['a']-=scope['b']");
|
||||
expect(compileExpr("a.b = !a.b", {})).toBe("scope['a'].b=!scope['a'].b");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user