QWeb is the template engine used by the OpenERP Web Client. It is an XML-based templating language, similar to Genshi, Thymeleaf or Facelets with a few peculiarities:
The rationale behind using QWeb instead of a more popular template syntax is that its extension mechanism is very similar to the openerp view inheritance mechanism. Like openerp views a QWeb template is an xml tree and therefore xpath or dom manipulations are easy to performs on it.
Here’s an example demonstrating most of the basic QWeb features:
<templates>
<div t-name="example_template" t-attf-class="base #{cls}">
<h4 t-if="title"><t t-esc="title"/></h4>
<ul>
<li t-foreach="items" t-as="item" t-att-class="item_parity">
<t t-call="example_template.sub">
<t t-set="arg" t-value="item_value"/>
</t>
</li>
</ul>
</div>
<t t-name="example_template.sub">
<t t-esc="arg.name"/>
<dl>
<t t-foreach="arg.tags" t-as="tag" t-if="tag_index lt 5">
<dt><t t-esc="tag"/></dt>
<dd><t t-esc="tag_value"/></dd>
</t>
</dl>
</t>
</templates>
rendered with the following context:
{
"class1": "foo",
"title": "Random Title",
"items": [
{ "name": "foo", "tags": {"bar": "baz", "qux": "quux"} },
{ "name": "Lorem", "tags": {
"ipsum": "dolor",
"sit": "amet",
"consectetur": "adipiscing",
"elit": "Sed",
"hendrerit": "ullamcorper",
"ante": "id",
"vestibulum": "Lorem",
"ipsum": "dolor",
"sit": "amet"
}
}
]
}
will yield this section of HTML document (reformated for readability):
<div class="base foo">
<h4>Random Title</h4>
<ul>
<li class="even">
foo
<dl>
<dt>bar</dt>
<dd>baz</dd>
<dt>qux</dt>
<dd>quux</dd>
</dl>
</li>
<li class="odd">
Lorem
<dl>
<dt>ipsum</dt>
<dd>dolor</dd>
<dt>sit</dt>
<dd>amet</dd>
<dt>consectetur</dt>
<dd>adipiscing</dd>
<dt>elit</dt>
<dd>Sed</dd>
<dt>hendrerit</dt>
<dd>ullamcorper</dd>
</dl>
</li>
</ul>
</div>
While QWeb implements a number of attributes and methods for customization and configuration, only two things are really important to the user:
The QWeb “renderer”, handles most of QWeb’s logic (loading, parsing, compiling and rendering templates).
OpenERP Web instantiates one for the user, and sets it to instance.web.qweb. It also loads all the template files of the various modules into that QWeb instance.
A QWeb2.Engine() also serves as a “template namespace”.
Renders a previously loaded template to a String, using context (if provided) to find the variables accessed during template rendering (e.g. strings to display).
Arguments: |
|
---|---|
Returns: | String |
The engine exposes an other method which may be useful in some cases (e.g. if you need a separate template namespace with, in OpenERP Web, Kanban views get their own QWeb2.Engine() instance so their templates don’t collide with more general “module” templates):
Loads a template file (a collection of templates) in the QWeb instance. The templates can be specified as:
A QWeb2.Engine() also exposes various attributes for behavior customization:
Prefix used to recognize directives during parsing. A string. By default, t.
Boolean flag putting the engine in “debug mode”. Normally, QWeb intercepts any error raised during template execution. In debug mode, it leaves all exceptions go through without intercepting them.
The jQuery instance used during template inheritance processing. Defaults to window.jQuery.
A Function. If present, called before compiling each DOM node to template code. In OpenERP Web, this is used to automatically translate text content and some attributes in templates. Defaults to null.
A basic QWeb template is nothing more than an XHTML document (as it must be valid XML), which will be output as-is. But the rendering can be customized with bits of logic called “directives”. Directives are attributes elements prefixed by prefix (this document will use the default prefix t, as does OpenERP Web).
A directive will usually control or alter the output of the element it is set on. If no suitable element is available, the prefix itself can be used as a “no-operation” element solely for supporting directives (or internal content, which will be rendered). This means:
<t>Something something</t>
will simply output the string “Something something” (the element itself will be skipped and “unwrapped”):
var e = new QWeb2.Engine();
e.add_template('<templates>\
<t t-name="test1"><t>Test 1</t></t>\
<t t-name="test2"><span>Test 2</span></t>\
</templates>');
e.render('test1'); // Test 1
e.render('test2'); // <span>Test 2</span>
Note
The conventions used in directive descriptions are the following:
Note
Expression actually supports a few extensions on the javascript syntax: because some syntactic elements of javascript are not compatible with XML and must be escaped, text substitutions are performed from forms which don’t need to be escaped. Thus the following “keyword operators” are available in an Expression: and (maps to &&), or (maps to ||), gt (maps to >), gte (maps to >=), lt (maps to <) and lte (maps to <=).
Parameters: | name (String) – an arbitrary javascript string. Each template name is unique in a given QWeb2.Engine() instance, defining a new template with an existing name will overwrite the previous one without warning. When multiple templates are related, it is customary to use dotted names as a kind of “namespace” e.g. foo and foo.bar which will be used either by foo or by a sub-widget of the widget used by foo. |
---|
Templates can only be defined as the children of the document root. The document root’s name is irrelevant (it’s not checked) but is usually <templates> for simplicity.
<templates>
<t t-name="template1">
<!-- template code -->
</t>
</templates>
t-name can be used on an element with an output as well:
<templates>
<div t-name="template2">
<!-- template code -->
</div>
</templates>
which ensures the template has a single root (if a template has multiple roots and is then passed directly to jQuery, odd things occur).
Parameters: | content (Expression) – |
---|
Evaluates, html-escapes and outputs content.
Parameters: | content (Format) – |
---|
Similar to t-esc but evaluates a Format instead of just an expression.
Parameters: | content (Expression) – |
---|
Similar to t-esc but does not html-escape the result of evaluating content. Should only ever be used for known-secure content, or will be an XSS attack vector.
Parameters: | content (Format) – |
---|
Format-based version of t-raw.
Parameters: | map (Expression) – |
---|
Evaluates map expecting an Object result, sets each key:value pair as an attribute (and its value) on the holder element:
<span t-att="{foo: 3, bar: 42}"/>
will yield
<span foo="3" bar="42"/>
Parameters: |
|
---|
Evaluates value and sets it on the attribute ATTNAME on the holder element.
If value‘s result is undefined, suppresses the creation of the attribute.
Parameters: |
|
---|
Similar to t-att-* but the value of the attribute is specified via a Format instead of an expression. Useful for specifying e.g. classes mixing literal classes and computed ones.
Parameters: |
|
---|
Creates a new binding in the template context. If value is specified, evaluates it and sets it to the specified name. Otherwise, processes BODY and uses that instead.
Parameters: | condition (Expression) – |
---|
Evaluates condition, suppresses the output of the holder element and its content of the result is falsy.
Parameters: |
|
---|
Evaluates iterable, iterates on it and evaluates the holder element and its body once per iteration round.
If name is not specified, computes a name based on iterable (by replacing non-Name characters by _).
If iterable yields a Number, treats it as a range from 0 to that number (excluded).
While iterating, t-foreach adds a number of variables in the context:
Parameters: |
|
---|
Calls the specified template and returns its result. If BODY is specified, it is evaluated before calling template and can be used to specify e.g. parameters. This usage is similar to call-template with with-param in XSLT.
Parameters: | template (String) – name of the template to extend |
---|
Works similarly to OpenERP models: if used on its own, will alter the specified template in-place; if used in conjunction with t-name will create a new template using the old one as a base.
BODY should be a sequence of t-jquery alteration directives.
Parameters: |
|
---|
If operation is specified, applies the selector to the parent template to find a context node, then applies operation (as a jQuery operation) to the context node, passing BODY as parameter.
Note
replace maps to jQuery’s replaceWith(newContent), inner maps to html(htmlString).
If operation is not provided, BODY is evaluated as javascript code, with the context node as this.
Warning
While this second form is much more powerful than the first, it is also much harder to read and maintain and should be avoided. It is usually possible to either avoid it or replace it with a sequence of t-jquery:t-operation:.
Parameters: | expression (Expression) – |
---|
Evaluates the provided expression (in the current template context) and logs its result via console.log.
Injects a debugger breakpoint (via the debugger; statement) in the compiled template output.
Parameters: |
|
---|
Injects the provided BODY javascript code into the compiled template, passing it the current template context using the name specified by context.