mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] qweb: allow to combine t-esc with other directives
With this rev., when a t-esc is not set on a <t> tag, we create it inside the node on which it is set, to ensure that the t-esc directive is always set on <t> tags. Same applies for t-raw. Closes #324
This commit is contained in:
committed by
Géry Debongnie
parent
2f27768be2
commit
0928c189f4
@@ -80,11 +80,6 @@ QWeb.addDirective({
|
|||||||
name: "esc",
|
name: "esc",
|
||||||
priority: 70,
|
priority: 70,
|
||||||
atNodeEncounter({ node, qweb, ctx }): boolean {
|
atNodeEncounter({ node, qweb, ctx }): boolean {
|
||||||
if (node.nodeName !== "t") {
|
|
||||||
let nodeID = qweb._compileGenericNode(node, ctx);
|
|
||||||
ctx = ctx.withParent(nodeID);
|
|
||||||
ctx = ctx.subContext("currentKey", ctx.lastNodeKey);
|
|
||||||
}
|
|
||||||
let value = ctx.getValue(node.getAttribute("t-esc")!);
|
let value = ctx.getValue(node.getAttribute("t-esc")!);
|
||||||
compileValueNode(value, node, qweb, ctx.subContext("escaping", true));
|
compileValueNode(value, node, qweb, ctx.subContext("escaping", true));
|
||||||
return true;
|
return true;
|
||||||
@@ -95,11 +90,6 @@ QWeb.addDirective({
|
|||||||
name: "raw",
|
name: "raw",
|
||||||
priority: 80,
|
priority: 80,
|
||||||
atNodeEncounter({ node, qweb, ctx }): boolean {
|
atNodeEncounter({ node, qweb, ctx }): boolean {
|
||||||
if (node.nodeName !== "t") {
|
|
||||||
let nodeID = qweb._compileGenericNode(node, ctx);
|
|
||||||
ctx = ctx.withParent(nodeID);
|
|
||||||
ctx = ctx.subContext("currentKey", ctx.lastNodeKey);
|
|
||||||
}
|
|
||||||
let value = ctx.getValue(node.getAttribute("t-raw")!);
|
let value = ctx.getValue(node.getAttribute("t-raw")!);
|
||||||
compileValueNode(value, node, qweb, ctx);
|
compileValueNode(value, node, qweb, ctx);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+10
-2
@@ -449,8 +449,6 @@ export class QWeb extends EventBus {
|
|||||||
fullName: string;
|
fullName: string;
|
||||||
}[] = [];
|
}[] = [];
|
||||||
|
|
||||||
let withHandlers = false;
|
|
||||||
|
|
||||||
// maybe this is not optimal: we iterate on all attributes here, and again
|
// maybe this is not optimal: we iterate on all attributes here, and again
|
||||||
// just after for each directive.
|
// just after for each directive.
|
||||||
for (let i = 0; i < attributes.length; i++) {
|
for (let i = 0; i < attributes.length; i++) {
|
||||||
@@ -460,11 +458,21 @@ export class QWeb extends EventBus {
|
|||||||
if (!(dName in QWeb.DIRECTIVE_NAMES)) {
|
if (!(dName in QWeb.DIRECTIVE_NAMES)) {
|
||||||
throw new Error(`Unknown QWeb directive: '${attrName}'`);
|
throw new Error(`Unknown QWeb directive: '${attrName}'`);
|
||||||
}
|
}
|
||||||
|
if (node.tagName !== 't' && (attrName === 't-esc' || attrName === 't-raw')) {
|
||||||
|
const tNode = document.createElement('t');
|
||||||
|
tNode.setAttribute(attrName, node.getAttribute(attrName)!);
|
||||||
|
for (let child of Array.from(node.childNodes)) {
|
||||||
|
tNode.appendChild(child);
|
||||||
|
}
|
||||||
|
node.appendChild(tNode);
|
||||||
|
node.removeAttribute(attrName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DIR_N = QWeb.DIRECTIVES.length;
|
const DIR_N = QWeb.DIRECTIVES.length;
|
||||||
const ATTR_N = attributes.length;
|
const ATTR_N = attributes.length;
|
||||||
|
let withHandlers = false;
|
||||||
for (let i = 0; i < DIR_N; i++) {
|
for (let i = 0; i < DIR_N; i++) {
|
||||||
let directive = QWeb.DIRECTIVES[i];
|
let directive = QWeb.DIRECTIVES[i];
|
||||||
let fullName;
|
let fullName;
|
||||||
|
|||||||
@@ -614,7 +614,7 @@ exports[`misc global 1`] = `
|
|||||||
context.value_index = i;
|
context.value_index = i;
|
||||||
context.value = _3[i];
|
context.value = _3[i];
|
||||||
context.value_value = _4[i];
|
context.value_value = _4[i];
|
||||||
let c5 = [], p5 = {key:5,on:{}};
|
let c5 = [], p5 = {key:5};
|
||||||
var vn5 = h('span', p5, c5);
|
var vn5 = h('span', p5, c5);
|
||||||
c1.push(vn5);
|
c1.push(vn5);
|
||||||
var _6 = context['value'];
|
var _6 = context['value'];
|
||||||
@@ -624,12 +624,12 @@ exports[`misc global 1`] = `
|
|||||||
{
|
{
|
||||||
let _11 = 'bbb';
|
let _11 = 'bbb';
|
||||||
var _13 = 'agüero';
|
var _13 = 'agüero';
|
||||||
let c14 = [], p14 = {key:14,attrs:{\\"falló\\": _13},on:{}};
|
let c14 = [], p14 = {key:14,attrs:{\\"falló\\": _13}};
|
||||||
var vn14 = h('Año', p14, c14);
|
var vn14 = h('año', p14, c14);
|
||||||
c1.push(vn14);
|
c1.push(vn14);
|
||||||
{
|
{
|
||||||
let _15 = 'aaa';
|
let _15 = 'aaa';
|
||||||
let c16 = [], p16 = {key:16,on:{}};
|
let c16 = [], p16 = {key:16};
|
||||||
var vn16 = h('span', p16, c16);
|
var vn16 = h('span', p16, c16);
|
||||||
c14.push(vn16);
|
c14.push(vn16);
|
||||||
if (_15 || _15 === 0) {
|
if (_15 || _15 === 0) {
|
||||||
@@ -638,7 +638,7 @@ exports[`misc global 1`] = `
|
|||||||
c16.push({text: \`foo default\`});
|
c16.push({text: \`foo default\`});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let c17 = [], p17 = {key:17,on:{}};
|
let c17 = [], p17 = {key:17};
|
||||||
var vn17 = h('span', p17, c17);
|
var vn17 = h('span', p17, c17);
|
||||||
c14.push(vn17);
|
c14.push(vn17);
|
||||||
var _18 = context['foo'];
|
var _18 = context['foo'];
|
||||||
@@ -648,7 +648,7 @@ exports[`misc global 1`] = `
|
|||||||
c17.push({text: \`foo default\`});
|
c17.push({text: \`foo default\`});
|
||||||
}
|
}
|
||||||
var _19 = 'bbb';
|
var _19 = 'bbb';
|
||||||
let c20 = [], p20 = {key:20,on:{}};
|
let c20 = [], p20 = {key:20};
|
||||||
var vn20 = h('span', p20, c20);
|
var vn20 = h('span', p20, c20);
|
||||||
c14.push(vn20);
|
c14.push(vn20);
|
||||||
if (_19 || _19 === 0) {
|
if (_19 || _19 === 0) {
|
||||||
@@ -658,7 +658,7 @@ exports[`misc global 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let c21 = [], p21 = {key:21,on:{}};
|
let c21 = [], p21 = {key:21};
|
||||||
var vn21 = h('div', p21, c21);
|
var vn21 = h('div', p21, c21);
|
||||||
c1.push(vn21);
|
c1.push(vn21);
|
||||||
var _22 = context['toto'];
|
var _22 = context['toto'];
|
||||||
@@ -1256,7 +1256,7 @@ exports[`t-esc escaping on a node 1`] = `
|
|||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
var h = this.h;
|
var h = this.h;
|
||||||
let c1 = [], p1 = {key:1,on:{}};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('span', p1, c1);
|
var vn1 = h('span', p1, c1);
|
||||||
result = vn1;
|
result = vn1;
|
||||||
var _2 = 'ok';
|
var _2 = 'ok';
|
||||||
@@ -1271,7 +1271,7 @@ exports[`t-esc escaping on a node with a body 1`] = `
|
|||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
var h = this.h;
|
var h = this.h;
|
||||||
let c1 = [], p1 = {key:1,on:{}};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('span', p1, c1);
|
var vn1 = h('span', p1, c1);
|
||||||
result = vn1;
|
result = vn1;
|
||||||
var _2 = 'ok';
|
var _2 = 'ok';
|
||||||
@@ -1288,7 +1288,7 @@ exports[`t-esc escaping on a node with a body, as a default 1`] = `
|
|||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
var h = this.h;
|
var h = this.h;
|
||||||
let c1 = [], p1 = {key:1,on:{}};
|
let c1 = [], p1 = {key:1};
|
||||||
var vn1 = h('span', p1, c1);
|
var vn1 = h('span', p1, c1);
|
||||||
result = vn1;
|
result = vn1;
|
||||||
var _2 = context['var'];
|
var _2 = context['var'];
|
||||||
@@ -1701,6 +1701,59 @@ exports[`t-on handler is bound to proper owner 1`] = `
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`t-on t-on combined with t-esc 1`] = `
|
||||||
|
"function anonymous(context,extra
|
||||||
|
) {
|
||||||
|
let owner = context;
|
||||||
|
var h = this.h;
|
||||||
|
let c1 = [], p1 = {key:1};
|
||||||
|
var vn1 = h('div', p1, c1);
|
||||||
|
result = vn1;
|
||||||
|
let c2 = [], p2 = {key:2,on:{}};
|
||||||
|
var vn2 = h('button', p2, c2);
|
||||||
|
c1.push(vn2);
|
||||||
|
if (!context['onClick']) {
|
||||||
|
throw new Error('Missing handler \\\\'' + 'onClick' + \`\\\\' when evaluating template 'test'\`)
|
||||||
|
}
|
||||||
|
extra.handlers['click' + 2] = extra.handlers['click' + 2] || context['onClick'].bind(owner);
|
||||||
|
p2.on['click'] = extra.handlers['click' + 2];
|
||||||
|
var _3 = context['text'];
|
||||||
|
if (_3 || _3 === 0) {
|
||||||
|
c2.push({text: _3});
|
||||||
|
}
|
||||||
|
return vn1;
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`t-on t-on combined with t-raw 1`] = `
|
||||||
|
"function anonymous(context,extra
|
||||||
|
) {
|
||||||
|
let utils = this.constructor.utils;
|
||||||
|
let owner = context;
|
||||||
|
var h = this.h;
|
||||||
|
let c1 = [], p1 = {key:1};
|
||||||
|
var vn1 = h('div', p1, c1);
|
||||||
|
let c2 = [], p2 = {key:2,on:{}};
|
||||||
|
var vn2 = h('button', p2, c2);
|
||||||
|
c1.push(vn2);
|
||||||
|
if (!context['onClick']) {
|
||||||
|
throw new Error('Missing handler \\\\'' + 'onClick' + \`\\\\' when evaluating template 'test'\`)
|
||||||
|
}
|
||||||
|
extra.handlers['click' + 2] = extra.handlers['click' + 2] || context['onClick'].bind(owner);
|
||||||
|
p2.on['click'] = extra.handlers['click' + 2];
|
||||||
|
var _3 = context['html'];
|
||||||
|
if (_3 || _3 === 0) {
|
||||||
|
var frag4 = utils.getFragment(_3)
|
||||||
|
var p5 = {hook: {
|
||||||
|
insert: n => n.elm.parentNode.replaceChild(frag4, n.elm),
|
||||||
|
}};
|
||||||
|
var vn5 = h('div', p5)
|
||||||
|
c2.push(vn5);
|
||||||
|
}
|
||||||
|
return vn1;
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`t-on t-on with prevent and self modifiers (order matters) 1`] = `
|
exports[`t-on t-on with prevent and self modifiers (order matters) 1`] = `
|
||||||
"function anonymous(context,extra
|
"function anonymous(context,extra
|
||||||
) {
|
) {
|
||||||
|
|||||||
+39
-1
@@ -778,7 +778,7 @@ describe("foreach", () => {
|
|||||||
|
|
||||||
describe("misc", () => {
|
describe("misc", () => {
|
||||||
test("global", () => {
|
test("global", () => {
|
||||||
qweb.addTemplate("_callee-asc", `<Año t-att-falló="'agüero'" t-raw="0"/>`);
|
qweb.addTemplate("_callee-asc", `<año t-att-falló="'agüero'" t-raw="0"/>`);
|
||||||
qweb.addTemplate("_callee-uses-foo", `<span t-esc="foo">foo default</span>`);
|
qweb.addTemplate("_callee-uses-foo", `<span t-esc="foo">foo default</span>`);
|
||||||
qweb.addTemplate("_callee-asc-toto", `<div t-raw="toto">toto default</div>`);
|
qweb.addTemplate("_callee-asc-toto", `<div t-raw="toto">toto default</div>`);
|
||||||
qweb.addTemplate(
|
qweb.addTemplate(
|
||||||
@@ -1118,6 +1118,44 @@ describe("t-on", () => {
|
|||||||
|
|
||||||
expect(steps).toEqual([1, 2]);
|
expect(steps).toEqual([1, 2]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("t-on combined with t-esc", async () => {
|
||||||
|
expect.assertions(3);
|
||||||
|
qweb.addTemplate("test", `<div><button t-on-click="onClick" t-esc="text"/></div>`);
|
||||||
|
const steps:string[] = [];
|
||||||
|
const owner = {
|
||||||
|
text: 'Click here',
|
||||||
|
onClick() {
|
||||||
|
steps.push('onClick');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const node = <HTMLElement>renderToDOM(qweb, "test", owner, { handlers: [] });
|
||||||
|
expect(node.outerHTML).toBe(`<div><button>Click here</button></div>`);
|
||||||
|
|
||||||
|
node.querySelector("button")!.click();
|
||||||
|
|
||||||
|
expect(steps).toEqual(['onClick']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("t-on combined with t-raw", async () => {
|
||||||
|
expect.assertions(3);
|
||||||
|
qweb.addTemplate("test", `<div><button t-on-click="onClick" t-raw="html"/></div>`);
|
||||||
|
const steps:string[] = [];
|
||||||
|
const owner = {
|
||||||
|
html: 'Click <b>here</b>',
|
||||||
|
onClick() {
|
||||||
|
steps.push('onClick');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const node = <HTMLElement>renderToDOM(qweb, "test", owner, { handlers: [] });
|
||||||
|
expect(node.outerHTML).toBe(`<div><button>Click <b>here</b></button></div>`);
|
||||||
|
|
||||||
|
node.querySelector("button")!.click();
|
||||||
|
|
||||||
|
expect(steps).toEqual(['onClick']);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("t-ref", () => {
|
describe("t-ref", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user