mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
+5
-4
@@ -677,7 +677,6 @@ to event `menu-loaded` will receive the payload in its `someMethod` handler
|
||||
|
||||
By convention, we use KebabCase for the name of _business_ events.
|
||||
|
||||
|
||||
The `t-on` directive allows to prebind some arguments. For example,
|
||||
|
||||
```xml
|
||||
@@ -695,10 +694,12 @@ One can also directly specify inline statements. For example,
|
||||
|
||||
Here, `state` must be defined in the rendering context (typically the component)
|
||||
as it will be translated to:
|
||||
```js
|
||||
button.addEventListener("click", () => { component.state.counter++; });
|
||||
```
|
||||
|
||||
```js
|
||||
button.addEventListener("click", () => {
|
||||
component.state.counter++;
|
||||
});
|
||||
```
|
||||
|
||||
In order to remove the DOM event details from the event handlers (like calls to
|
||||
`event.preventDefault`) and let them focus on data logic, _modifiers_ can be
|
||||
|
||||
+10
-3
@@ -1,8 +1,15 @@
|
||||
# 🦉 Tags 🦉
|
||||
|
||||
## Content
|
||||
|
||||
- [Overview](#overview)
|
||||
- [`xml` tag](#xml-tag)
|
||||
|
||||
## Overview
|
||||
|
||||
Tags are very small helpers to make it easy to write inline templates. There is
|
||||
only one currently available tag: `xml`, but we plan to add other tags later,
|
||||
such as a `css` tag, which will be used to write single file components.
|
||||
such as a `css` tag, which will be used to write [single file components](tooling.md#single-file-component).
|
||||
|
||||
## XML tag
|
||||
|
||||
@@ -31,8 +38,8 @@ With tags, this process is slightly simplified. The name is uniquely generated,
|
||||
and the template is automatically registered:
|
||||
|
||||
```js
|
||||
import { Component } from 'owl'
|
||||
import { xml } from 'owl/tags'
|
||||
const { Component } = owl;
|
||||
const { xml } = owl.tags;
|
||||
|
||||
class MyComponent extends Component {
|
||||
static template = xml`
|
||||
|
||||
+18
-4
@@ -60,12 +60,21 @@ useful to compare various performance metrics on some tasks.
|
||||
|
||||
## Single File Component
|
||||
|
||||
If you want to have `xml` syntax highlighting while using the `xml` helper which
|
||||
helps you define inline templates, there is a VS Code addon `Comment tagged template`
|
||||
which, if installed, does exactly that. To enable it, you need to add a comment,
|
||||
like this:
|
||||
It is very useful to group code by feature instead of by type of file. It makes
|
||||
it easier to scale application to larger size.
|
||||
|
||||
To do so, Owl currently has a small helper that makes it easy to define a
|
||||
template inside a javascript (or typescript) file: the [`xml`](tags.md#xml-tag)
|
||||
helper. With this, a template is automatically registered to [QWeb](qweb.md).
|
||||
|
||||
This means that the template and the javascript code can be defined in the same
|
||||
file. It is not currently possible to add css to the same file, but Owl may
|
||||
get a `css` tag helper later.
|
||||
|
||||
```js
|
||||
const { Component } = owl;
|
||||
const { xml } = owl.tags;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// TEMPLATE
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -85,3 +94,8 @@ class MyComponent extends Component {
|
||||
// rest of component...
|
||||
}
|
||||
```
|
||||
|
||||
Note that the above example has an inline xml comment, just after the `xml` call.
|
||||
This is useful for some editor plugins, such as the VS Code addon
|
||||
`Comment tagged template`, which, if installed, add syntax highlighting to the
|
||||
content of the template string.
|
||||
|
||||
@@ -58,7 +58,9 @@ QWeb.addDirective({
|
||||
ctx.addLine(`p${nodeID}.on['${eventName}'] = extra.handlers['${eventName}' + ${nodeID}];`);
|
||||
} else {
|
||||
const handlerKey = `handler${ctx.generateID()}`;
|
||||
ctx.addLine(`const ${handlerKey} = context['${handlerName}'] && context['${handlerName}'].bind(${params});`);
|
||||
ctx.addLine(
|
||||
`const ${handlerKey} = context['${handlerName}'] && context['${handlerName}'].bind(${params});`
|
||||
);
|
||||
handler += `if (${handlerKey}) { ${handlerKey}(e); } else { context.${value}; }`;
|
||||
handler += `}`;
|
||||
ctx.addLine(`p${nodeID}.on['${eventName}'] = ${handler};`);
|
||||
|
||||
@@ -2142,7 +2142,7 @@ describe("other directives with t-component", () => {
|
||||
<Child t-on-ev="handler"/>
|
||||
</div>`;
|
||||
static components = { Child };
|
||||
state = useState({counter: 0});
|
||||
state = useState({ counter: 0 });
|
||||
get handler() {
|
||||
this.state.counter++;
|
||||
return () => {};
|
||||
@@ -2152,12 +2152,12 @@ describe("other directives with t-component", () => {
|
||||
await parent.mount(fixture);
|
||||
|
||||
expect(env.qweb.templates[Parent.template].fn.toString()).toMatchSnapshot();
|
||||
expect(fixture.innerHTML).toBe('<div>0<span></span></div>');
|
||||
expect(fixture.innerHTML).toBe("<div>0<span></span></div>");
|
||||
|
||||
let child = children(parent)[0];
|
||||
child.trigger("ev");
|
||||
await nextTick();
|
||||
expect(fixture.innerHTML).toBe('<div>1<span></span></div>');
|
||||
expect(fixture.innerHTML).toBe("<div>1<span></span></div>");
|
||||
});
|
||||
|
||||
test("t-on with inline statement", async () => {
|
||||
@@ -2171,18 +2171,18 @@ describe("other directives with t-component", () => {
|
||||
<Child t-on-ev="state.counter++"/>
|
||||
</div>`;
|
||||
static components = { Child };
|
||||
state = useState({counter: 0});
|
||||
state = useState({ counter: 0 });
|
||||
}
|
||||
const parent = new Parent(env);
|
||||
await parent.mount(fixture);
|
||||
|
||||
expect(env.qweb.templates[Parent.template].fn.toString()).toMatchSnapshot();
|
||||
expect(fixture.innerHTML).toBe('<div>0<span></span></div>');
|
||||
expect(fixture.innerHTML).toBe("<div>0<span></span></div>");
|
||||
|
||||
let child = children(parent)[0];
|
||||
child.trigger("ev");
|
||||
await nextTick();
|
||||
expect(fixture.innerHTML).toBe('<div>1<span></span></div>');
|
||||
expect(fixture.innerHTML).toBe("<div>1<span></span></div>");
|
||||
});
|
||||
|
||||
test("t-on with no handler (only modifiers)", async () => {
|
||||
|
||||
@@ -1044,8 +1044,8 @@ describe("t-on", () => {
|
||||
qweb.addTemplate("test", `<button t-on-click="state.counter++">Click</button>`);
|
||||
let owner = {
|
||||
state: {
|
||||
counter: 0,
|
||||
},
|
||||
counter: 0
|
||||
}
|
||||
};
|
||||
const node = renderToDOM(qweb, "test", owner, { handlers: [] });
|
||||
expect(owner.state.counter).toBe(0);
|
||||
@@ -1058,8 +1058,10 @@ describe("t-on", () => {
|
||||
let owner = {
|
||||
state: {
|
||||
counter: 0,
|
||||
incrementCounter: (inc) => { owner.state.counter += inc; },
|
||||
},
|
||||
incrementCounter: inc => {
|
||||
owner.state.counter += inc;
|
||||
}
|
||||
}
|
||||
};
|
||||
const node = renderToDOM(qweb, "test", owner, { handlers: [] });
|
||||
expect(owner.state.counter).toBe(0);
|
||||
@@ -1223,7 +1225,7 @@ describe("t-on", () => {
|
||||
);
|
||||
const node = renderToDOM(qweb, "test", {}, { handlers: [] });
|
||||
|
||||
node.addEventListener('click', (e) => {
|
||||
node.addEventListener("click", e => {
|
||||
expect(e.defaultPrevented).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user