qPlate is the primary templating engine. It is an XML templating engine and used mostly to generate HTML fragments and pages. Can be used server side with nodejs or client side.
Template directives are specified as XML attributes prefixed with t-
by default (you can choose it), for instance t-if
for conditionals, with elements and other attributes being rendered directly.
To avoid element rendering, a placeholder element <t>
is also available, which executes its directive but doesn't generate any output in and of itself:
<t t-if="condition"> <p>Test</p> </t>
will result in:
<p>Test</p>
if condition
is true, but:
<div t-if="condition"> <p>Test</p> </div>
will result in:
<div> <p>Test</p> </div>
qPlate has a primary output directive which automatically HTML-escape its
content limiting XSS risks when displaying user-provided content: esc
.
esc
takes an expression, evaluates it and prints the content:
<p><t t-esc="value"/></p>
rendered with the value value
set to 42
yields:
<p>42</p>
There is one other output directive raw
which behaves the same as
respectively esc
but does not HTML-escape its output. It can be useful
to display separately constructed markup (e.g. from functions) or already
sanitized user-provided markup.
qPlate has a conditional directive if
, which evaluates an expression given
as attribute value:
<div> <t t-if="condition"> <p>ok</p> </t> </div>
The element is rendered if the condition is true:
<div> <p>ok</p> </div>
but if the condition is false it is removed from the result:
<div> </div>
The conditional rendering applies to the bearer of the directive, which does
not have to be <t>
:
<div> <p t-if="condition">ok</p> </div>
will give the same results as the previous example.
qPlate has an iteration directive foreach
which take an expression returning
the collection to iterate on, and a second parameter t-as
providing the
name to use for the "current item" of the iteration:
<t t-foreach="[1, 2, 3]" t-as="i"> <p><t t-esc="i"/></p> </t>
will be rendered as:
<p>1</p> <p>2</p> <p>3</p>
Like conditions, foreach
applies to the element bearing the directive's
attribute, and
<p t-foreach="[1, 2, 3]" t-as="i"> <t t-esc="i"/> </p>
is equivalent to the previous example.
foreach
can iterate on an array (the current item will be the current
value), a mapping (the current item will be the current key) or an integer
(equivalent to iterating on an array between 0 inclusive and the provided
integer exclusive).
In addition to the name passed via t-as
, foreach
provides a few other
variables for various data points:
Warning
$as
will be replaced by the name passed to t-as
$as_all
- the object being iterated over
$as_value
- the current iteration value, identical to
$as
for lists and integers, but for mappings it provides the value (where$as
provides the key) $as_index
- the current iteration index (the first item of the iteration has index 0)
$as_size
- the size of the collection if it is available
$as_first
- whether the current item is the first of the iteration (equivalent to
$as_index == 0
) $as_last
- whether the current item is the last of the iteration (equivalent to
$as_index + 1 == $as_size
), requires the iteratee's size be available $as_parity
- either
"even"
or"odd"
, the parity of the current iteration round $as_even
- a boolean flag indicating that the current iteration round is on an even index
$as_odd
- a boolean flag indicating that the current iteration round is on an odd index
These extra variables provided and all new variables created into the
foreach
are only available in the scope of the``foreach``. If the
variable exists outside the context of the foreach
, the value is copied
at the end of the foreach into the global context.
<t t-set="existing_variable" t-value="False"/> <!-- existing_variable now False --><p t-foreach="[1, 2, 3]" t-as="i"> <t t-set="existing_variable" t-value="True"/> <t t-set="new_variable" t-value="True"/> <!-- existing_variable and new_variable now True --> </p>
<!-- existing_variable always True --> <!-- new_variable undefined -->
qPlate can compute attributes on-the-fly and set the result of the computation
on the output node. This is done via the t-att
(attribute) directive which
exists in 4 different forms:
$name="{{...}}"
-
an attribute called
$name
is created, the attribute value contains in the braces is evaluated and the result is set as the attribute's value:<div class="static {{'add-class'}}"/>
will be rendered as:
<div class="static add-class"></div>
t-att-$name
-
an attribute called
$name
is created, the attribute value is evaluated and the result is set as the attribute's value:<div t-att-a="42"/>
will be rendered as:
<div a="42"></div>
t-attf-$name
-
same as previous, but the parameter is a format string instead of just an expression, often useful to mix literal and non-literal string (e.g. classes):
<t t-foreach="[1, 2, 3]" t-as="item"> <li t-attf-class="row {{ item_parity }}"><t t-esc="item"/></li> </t>
will be rendered as:
<li class="row even">1</li> <li class="row odd">2</li> <li class="row even">3</li>
t-att=mapping
-
if the parameter is a mapping, each (key, value) pair generates a new attribute and its value:
<div t-att="{'a': 1, 'b': 2}"/>
will be rendered as:
<div a="1" b="2"></div>
t-att=pair
-
if the parameter is a pair (tuple or array of 2 element), the first item of the pair is the name of the attribute and the second item is the value:
<div t-att="['a', 'b']"/>
will be rendered as:
<div a="b"></div>
qPlate allows creating variables from within the template, to memoize a computation (to use it multiple times), give a piece of data a clearer name, ...
This is done via the set
directive, which takes the name of the variable
to create. The value to set can be provided in two ways:
-
a
t-value
attribute containing an expression, and the result of its evaluation will be set:<t t-set="foo" t-value="2 + 1"/> <t t-esc="foo"/>
will print
3
-
if there is no
t-value
attribute, the node's body is rendered and set as the variable's value:<t t-set="foo"> <li>ok</li> </t> <t t-esc="foo"/>
will generate
<li>ok</li>
(the content is escaped as we used theesc
directive)Note
using the result of this operation is a significant use-case for the
raw
directive.
qPlate templates can be used for top-level rendering, but they can also be used
from within another template (to avoid duplication or give names to parts of
templates) using the t-call
directive:
<t t-call="other-template"/>
This calls the named template with the execution context of the parent, if
other_template
is defined as:
<p><t t-value="var"/></p>
the call above will be rendered as <p/>
(no content), but:
<t t-set="var" t-value="1"/> <t t-call="other-template"/>
will be rendered as <p>1</p>
.
However this has the problem of being visible from outside the t-call
.
Alternatively, content set in the body of the call
directive will be
evaluated before calling the sub-template, and can alter a local context:
<t t-call="other-template"> <t t-set="var" t-value="1"/> </t> <!-- "var" does not exist here -->
The body of the call
directive can be arbitrarily complex (not just
set
directives), and its rendered form will be available within the called
template as a magical 0
variable:
<div> This template was called with content: <t t-raw="0"/> </div>
being called thus:
<t t-call="other-template"> <em>content</em> </t>
will result in:
<div> This template was called with content: <em>content</em> </div>
Template inheritance is used to alter existing templates in-place, e.g. to add information to templates created by an other modules.
Template inheritance is performed via the t-extend
directive which takes the name of the template to alter as parameter.
The alteration is then performed with any number of t-xpath
sub-directives:
<t t-extend="base.template"> <t t-xpath="//ul" t-operation="append"> <li>new element</li> </t> <t t-xpath="//ul/li/@name" t-operation="replace"> <li>attribute value</li> </t> </t>
The t-xpath
directives takes a Xpath selector. This selector is used on the extended template to select context nodes to which the specified t-operation
is applied:
append
- the node's body is appended at the end of the context node (after the context node's last child)
prepend
- the node's body is prepended to the context node (inserted before the context node's first child)
replace
- the node's body is used to replace the context node itself
before
- the node's body is inserted right before the context node (not available when target an attribute)
after
- the node's body is inserted right after the context node (not available when target an attribute)
inner
- the node's body replaces the context node's children (not available when target an attribute)
- No operation
-
if no
t-operation
is specified, the template body is interpreted as javascript code and executed with the context node asthis
Warning
while much more powerful than other operations, this mode is also much harder to debug and maintain, it is recommended to avoid it
The javascript qPlate implementation provides a few debugging hooks:
t-log
-
takes an expression parameter, evaluates the expression during rendering and logs its result with
console.log
:<t t-set="foo" t-value="42"/> <t t-log="foo"/>
will print
42
to the console t-debug
-
triggers a debugger breakpoint during template rendering:
<t t-if="a_test"> <t t-debug=""> </t>
will stop execution if debugging is active (exact condition depend on the browser and its development tools)
t-js
-
the node's body is javascript code executed during template rendering. Takes a
context
parameter, which is the name under which the rendering context will be available in thet-js
's body:<t t-set="foo" t-value="42"/> <t t-js="ctx"> console.log("Foo is", ctx.foo); </t>
Expression | Refers to |
---|---|
|
All |
|
All |
|
All |
|
The document element ( |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All elements that are the children of |
|
All |
|
All grandchildren elements of the current context. |
|
All elements with the |
|
The |
|
The |
|
Returns an empty node set, because attributes do not contain element children. This expression is allowed by the XML Path Language (XPath) grammar, but is not strictly valid. |
|
All |
|
The |
|
All attributes of the current element context. |
|
All |
|
All |
|
The first |
|
The third |
|
The |
|
All elements from the |
|
All attributes from the |
|
The first |
|
The first |
|
The first |
|
The second |
|
The last |
|
The last |
|
The last |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
All |
|
The first three books (1, 2, 3). |
|
All |
|
All |
|
all author elements containing any child element whose value is |
|
All |
|
All |
|
The first two |
|
The second text node in each |
|
The nearest |
|
The nearest |
|
The nearest |