mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] compiler: properly handle readonly attribute/readOnly property
Before this commit, Owl template compiler would handle readonly attribute as readonly properties. But this is incorrect, since the property is actually named readOnly. With this commit, we make sure that readonly AND readOnly are both interpreted as the `readOnly` property. This is due to the fact that QWeb does not discriminate between attribute and properties, so we have to infer which is which. closes #1362
This commit is contained in:
committed by
Sam Degueldre
parent
f892929c80
commit
cdad48d3a6
@@ -65,12 +65,13 @@ function isProp(tag: string, key: string): boolean {
|
|||||||
key === "indeterminate" ||
|
key === "indeterminate" ||
|
||||||
key === "value" ||
|
key === "value" ||
|
||||||
key === "readonly" ||
|
key === "readonly" ||
|
||||||
|
key === "readOnly" ||
|
||||||
key === "disabled"
|
key === "disabled"
|
||||||
);
|
);
|
||||||
case "option":
|
case "option":
|
||||||
return key === "selected" || key === "disabled";
|
return key === "selected" || key === "disabled";
|
||||||
case "textarea":
|
case "textarea":
|
||||||
return key === "value" || key === "readonly" || key === "disabled";
|
return key === "value" || key === "readonly" || key === "readOnly" || key === "disabled";
|
||||||
case "select":
|
case "select":
|
||||||
return key === "value" || key === "disabled";
|
return key === "value" || key === "disabled";
|
||||||
case "button":
|
case "button":
|
||||||
@@ -600,6 +601,10 @@ export class CodeGenerator {
|
|||||||
attrName = key === "t-att" ? null : key.slice(6);
|
attrName = key === "t-att" ? null : key.slice(6);
|
||||||
expr = compileExpr(ast.attrs[key]);
|
expr = compileExpr(ast.attrs[key]);
|
||||||
if (attrName && isProp(ast.tag, attrName)) {
|
if (attrName && isProp(ast.tag, attrName)) {
|
||||||
|
if (attrName === "readonly") {
|
||||||
|
// the property has a different name than the attribute
|
||||||
|
attrName = "readOnly";
|
||||||
|
}
|
||||||
// we force a new string or new boolean to bypass the equality check in blockdom when patching same value
|
// we force a new string or new boolean to bypass the equality check in blockdom when patching same value
|
||||||
if (attrName === "value") {
|
if (attrName === "value") {
|
||||||
// When the expression is falsy (except 0), fall back to an empty string
|
// When the expression is falsy (except 0), fall back to an empty string
|
||||||
|
|||||||
@@ -140,6 +140,60 @@ exports[`input, type checkbox, with t-att-checked (patching with same value 1`]
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`readonly and readOnly are both interpreted as the readOnly property 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<input readonly=\\"\\"/>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`readonly and readOnly are both interpreted as the readOnly property 2`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<input readOnly=\\"\\"/>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`readonly and readOnly are both interpreted as the readOnly property 3`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<input block-property-0=\\"readOnly\\"/>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let prop1 = new Boolean(ctx['val']);
|
||||||
|
return block1([prop1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`readonly and readOnly are both interpreted as the readOnly property 4`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<input block-property-0=\\"readOnly\\"/>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
let prop1 = new Boolean(ctx['val']);
|
||||||
|
return block1([prop1]);
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`select with t-att-value 1`] = `
|
exports[`select with t-att-value 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -186,3 +186,28 @@ test("select with t-att-value", () => {
|
|||||||
patch(bnode1, bnode2);
|
patch(bnode1, bnode2);
|
||||||
expect(elm.value).toBe("onion");
|
expect(elm.value).toBe("onion");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("readonly and readOnly are both interpreted as the readOnly property", () => {
|
||||||
|
// render input with initial value
|
||||||
|
const staticTemplates = [`<input readonly=""/>`, `<input readOnly=""/>`];
|
||||||
|
for (let template of staticTemplates) {
|
||||||
|
const fixture = makeTestFixture();
|
||||||
|
const bnode1 = renderToBdom(template);
|
||||||
|
mount(bnode1, fixture);
|
||||||
|
const input = fixture.querySelector("input")!;
|
||||||
|
expect(input.readOnly).toBe(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dynamicTemplates = [`<input t-att-readonly="val"/>`, `<input t-att-readOnly="val"/>`];
|
||||||
|
for (let template of dynamicTemplates) {
|
||||||
|
const fixture = makeTestFixture();
|
||||||
|
const bnode1 = renderToBdom(template, { val: true });
|
||||||
|
mount(bnode1, fixture);
|
||||||
|
const input = fixture.querySelector("input")!;
|
||||||
|
expect(input.readOnly).toBe(true);
|
||||||
|
|
||||||
|
const bnode2 = renderToBdom(template, { val: false });
|
||||||
|
patch(bnode1, bnode2);
|
||||||
|
expect(input.readOnly).toBe(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user