[FIX] qweb: support #{} syntax in attribute string interpolation

closes #113
This commit is contained in:
Géry Debongnie
2019-05-17 16:14:54 +02:00
parent a1e982aba5
commit a1d7e6c987
4 changed files with 42 additions and 7 deletions
+19 -3
View File
@@ -12,7 +12,8 @@
- [`t-set` directive](#t-set-directive) - [`t-set` directive](#t-set-directive)
- [`t-if` directive](#t-if-directive) - [`t-if` directive](#t-if-directive)
- [Expression evaluation](#expression-evaluation) - [Expression evaluation](#expression-evaluation)
- [`t-att` directive (dynamic attributes)](#t-att-directive-dynamic-attributes) - [Dynamic attributes (`t-att` and `t-attf` directives)](#dynamic-attributes-t-att-and-t-attf-directives)
- [`t-attf` directive (dynamic attributes)](#t-att-directive-dynamic-attributes)
- [`t-call` directive (sub templates)](#t-call-directive-sub-templates) - [`t-call` directive (sub templates)](#t-call-directive-sub-templates)
- [JS/OWL Specific Extensions](#jsowl-specific-extensions) - [JS/OWL Specific Extensions](#jsowl-specific-extensions)
@@ -257,7 +258,7 @@ compile time.
<div><p t-if="10 + 2 gt 5">ok</p></div> <div><p t-if="10 + 2 gt 5">ok</p></div>
``` ```
### `t-att` directive (dynamic attributes) ### Dynamic attributes (`t-att` and `t-attf` directives)
One can use the `t-att-` directive to add dynamic attributes. Its main use is to One can use the `t-att-` directive to add dynamic attributes. Its main use is to
evaluate an expression (at rendering time) and bind an attribute to its result: evaluate an expression (at rendering time) and bind an attribute to its result:
@@ -265,7 +266,7 @@ evaluate an expression (at rendering time) and bind an attribute to its result:
For example, if we have `id` set to 32 in the rendering context, For example, if we have `id` set to 32 in the rendering context,
```xml ```xml
<div t-att-data-action-id="id"/> <!-- result: <div data-action-id="32"></div> --> <div t-att-data-action-id="id"/> <!-- result: <div data-action-id="32"></div> -->
``` ```
If an expression evaluates to a falsy value, it will not be set at all: If an expression evaluates to a falsy value, it will not be set at all:
@@ -274,6 +275,21 @@ If an expression evaluates to a falsy value, it will not be set at all:
<div t-att-foo="false"/> <!-- result: <div></div> --> <div t-att-foo="false"/> <!-- result: <div></div> -->
``` ```
There is another way to format a string attribute: the `t-attf-` directive. With
it, you get string interpolation:
```xml
<div t-attf-foo="a {{value1}} is {{value2}} of {{value3}} ]"/>
<!-- result if values are set to 1,2 and 3: <div foo="a 0 is 1 of 2 ]"></div> -->
```
For historical reason, there is an alternate form of string interpolation:
```xml
<div t-attf-foo="a #{value1} is #{value2} of #{value3} ]"/>
<!-- result if values are set to 1,2 and 3: <div foo="a 0 is 1 of 2 ]"></div> -->
```
### `t-call` directive (sub templates) ### `t-call` directive (sub templates)
QWeb templates can be used for top level rendering, but they can also be used QWeb templates can be used for top level rendering, but they can also be used
+6 -4
View File
@@ -457,6 +457,9 @@ export class QWeb {
props.push(`${key}: _${val}`); props.push(`${key}: _${val}`);
} }
} }
function formatter(expr) {
return "${" + ctx.formatExpression(expr) + "}";
}
for (let i = 0; i < attributes.length; i++) { for (let i = 0; i < attributes.length; i++) {
let name = attributes[i].name; let name = attributes[i].name;
@@ -515,10 +518,9 @@ export class QWeb {
// attribute contains 'non letters' => we want to quote it // attribute contains 'non letters' => we want to quote it
attName = '"' + attName + '"'; attName = '"' + attName + '"';
} }
const formattedExpr = value!.replace( const formattedExpr = value!
/\{\{.*?\}\}/g, .replace(/\{\{.*?\}\}/g, s => formatter(s.slice(2, -2)))
s => "${" + ctx.formatExpression(s.slice(2, -2)) + "}" .replace(/\#\{.*?\}/g, s => formatter(s.slice(2, -1)));
);
const attID = ctx.generateID(); const attID = ctx.generateID();
let staticVal = (<Element>node).getAttribute(attName); let staticVal = (<Element>node).getAttribute(attName);
if (staticVal) { if (staticVal) {
+11
View File
@@ -93,6 +93,17 @@ exports[`attributes format expression 1`] = `
}" }"
`; `;
exports[`attributes format expression, other format 1`] = `
"function anonymous(context,extra
) {
var h = this.utils.h;
var _1 = \`\${context['value'] + 37}\`;
let c2 = [], p2 = {key:2,attrs:{foo: _1}};
var vn2 = h('div', p2, c2);
return vn2;
}"
`;
exports[`attributes format literal 1`] = ` exports[`attributes format literal 1`] = `
"function anonymous(context,extra "function anonymous(context,extra
) { ) {
+6
View File
@@ -511,6 +511,12 @@ describe("attributes", () => {
expect(result).toBe(`<div foo="42"></div>`); expect(result).toBe(`<div foo="42"></div>`);
}); });
test("format expression, other format", () => {
qweb.addTemplate("test", `<div t-attf-foo="#{value + 37}"/>`);
const result = renderToString(qweb, "test", { value: 5 });
expect(result).toBe(`<div foo="42"></div>`);
});
test("format multiple", () => { test("format multiple", () => {
qweb.addTemplate( qweb.addTemplate(
"test", "test",