🦉 Tags 🦉
Content
Overview
Tags are very small helpers intended to make it easy to write inline templates
or styles. There are currently two tags: css
and xml
. With these functions,
it is possible to write single file components.
XML tag
The xml
tag is certainly the most useful tag. It is used to define an inline
QWeb template for a component. Without tags, creating a standalone component
would look like this:
import { Component } from 'owl'
const name = 'some-unique-name';
const template = `
<div>
<span t-if="somecondition">text</span>
<button t-on-click="someMethod">Click</button>
</div>
`;
QWeb.registerTemplate(name, template);
class MyComponent extends Component {
static template = name;
...
}
With tags, this process is slightly simplified. The name is uniquely generated, and the template is automatically registered:
const { Component } = owl;
const { xml } = owl.tags;
class MyComponent extends Component {
static template = xml`
<div>
<span t-if="somecondition">text</span>
<button t-on-click="someMethod">Click</button>
</div>
`;
...
}
CSS tag
The CSS tag is useful to define a css stylesheet in the javascript file:
class MyComponent extends Component {
static template = xml`
<div class="my-component">some template</div>
`;
static css`
.my-component {
color: red;
}
`;
}
The css
tag registers internally the css information. Then, whenever the first
instance of the component is created, will add a <style>
tag to the document
<head>
.
Note that to make it more useful, like other css preprocessors, the css
tag
accepts a small extension of the css specification: css scopes can be nested,
and the rules will then be expanded by the css
helper:
.my-component {
display: block;
.sub-component h {
color: red;
}
}
will be formatted as:
.my-component {
display: block;
}
.my-component .sub-component h {
color: red;
}
This extension brings another useful feature: the &
selector which refers to
the parent selector. For example, we want our component to be red when hovered.
We would like to write something like:
.my-component {
display: block;
:hover {
color: red;
}
}
but it will be formatted as:
.my-component {
display: block;
}
.my-component :hover {
color: red;
}
The &
selector can be used to solve this problem:
.my-component {
display: block;
&:hover {
color: red;
}
}
will be formatted as:
.my-component {
display: block;
}
.my-component:hover {
color: red;
}
Now, there is no additional processing done by the css
tag. However, since it
is done in javascript at runtime, we actually have more power. For example:
- sharing values between javascript and css:
import { theme } from "./theme";
class MyComponent extends Component {
static template = xml`<div class="my-component">...</div>`;
static style = css`
.my-component {
color: ${theme.MAIN_COLOR};
background-color: ${theme.SECONDARY_color};
}
`;
}
- scoping rules to the current component:
import { generateUUID } from "./utils";
const uuid = generateUUID();
class MyComponent extends Component {
static template = xml`<div data-o-${uuid}="">...</div>`;
static style = css`
[data-o-${uuid}] {
color: red;
}
`;
}