QWeb ==== 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: * It's implemented fully in javascript and rendered in the browser. * Each template file (XML files) contains multiple templates, where template engine usually have a 1:1 mapping between template files and templates. * It has special support in OpenERP Web's :class:`~instance.web.Widget`, though it can be used outside of OpenERP Web (and it's possible to use :class:`~instance.web.Widget` without relying on the QWeb integration). 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: .. code-block:: xml

rendered with the following context: .. code-block:: json { "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): .. code-block:: html

Random Title

  • foo
    bar
    baz
    qux
    quux
  • Lorem
    ipsum
    dolor
    sit
    amet
    consectetur
    adipiscing
    elit
    Sed
    hendrerit
    ullamcorper
API --- While QWeb implements a number of attributes and methods for customization and configuration, only two things are really important to the user: .. js:class:: QWeb2.Engine 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 :js:class:`QWeb2.Engine` also serves as a "template namespace". .. js:function:: QWeb2.Engine.render(template[, context]) 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). :param String template: the name of the template to render :param Object context: the basic namespace to use for template rendering :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 :js:class:`QWeb2.Engine` instance so their templates don't collide with more general "module" templates): .. js:function:: QWeb2.Engine.add_template(templates) Loads a template file (a collection of templates) in the QWeb instance. The templates can be specified as: An XML string QWeb will attempt to parse it to an XML document then load it. A URL QWeb will attempt to download the URL content, then load the resulting XML string. A ``Document`` or ``Node`` QWeb will traverse the first level of the document (the child nodes of the provided root) and load any named template or template override. :type templates: String | Document | Node A :js:class:`QWeb2.Engine` also exposes various attributes for behavior customization: .. js:attribute:: QWeb2.Engine.prefix Prefix used to recognize :ref:`directives ` during parsing. A string. By default, ``t``. .. js:attribute:: QWeb2.Engine.debug 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. .. js:attribute:: QWeb2.Engine.jQuery The jQuery instance used during :ref:`template inheritance ` processing. Defaults to ``window.jQuery``. .. js:attribute:: QWeb2.Engine.preprocess_node 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``. .. _qweb-directives: Directives ---------- 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 :js:attr:`~QWeb2.Engine.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: .. code-block:: xml Something something will simply output the string "Something something" (the element itself will be skipped and "unwrapped"): .. code-block:: javascript var e = new QWeb2.Engine(); e.add_template('\ Test 1\ Test 2\ '); e.render('test1'); // Test 1 e.render('test2'); // Test 2 .. note:: The conventions used in directive descriptions are the following: * directives are described as compound functions, potentially with optional sections. Each section of the function name is an attribute of the element bearing the directive. * a special parameter is ``BODY``, which does not have a name and designates the content of the element. * special parameter types (aside from ``BODY`` which remains untyped) are ``Name``, which designates a valid javascript variable name, ``Expression`` which designates a valid javascript expression, and ``Format`` which designates a Ruby-style format string (a literal string with ``#{Expression}`` inclusions executed and replaced by their result) .. 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 ``<=``). .. _qweb-directives-templates: Defining Templates ++++++++++++++++++ .. _qweb-directive-name: .. function:: t-name=name :param String name: an arbitrary javascript string. Each template name is unique in a given :js:class:`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 ```` for simplicity. .. code-block:: xml :ref:`t-name ` can be used on an element with an output as well: .. code-block:: xml
which ensures the template has a single root (if a template has multiple roots and is then passed directly to jQuery, odd things occur). .. _qweb-directives-output: Output ++++++ .. _qweb-directive-esc: .. function:: t-esc=content :param Expression content: Evaluates, html-escapes and outputs ``content``. .. _qweb-directive-escf: .. function:: t-escf=content :param Format content: Similar to :ref:`t-esc ` but evaluates a ``Format`` instead of just an expression. .. _qweb-directive-raw: .. function:: t-raw=content :param Expression content: Similar to :ref:`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. .. _qweb-directive-rawf: .. function:: t-rawf=content :param Format content: ``Format``-based version of :ref:`t-raw `. .. _qweb-directive-att: .. function:: t-att=map :param Expression map: Evaluates ``map`` expecting an ``Object`` result, sets each key:value pair as an attribute (and its value) on the holder element: .. code-block:: xml will yield .. code-block:: html .. function:: t-att-ATTNAME=value :param Name ATTNAME: :param Expression value: 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. .. _qweb-directive-attf: .. function:: t-attf-ATTNAME=value :param Name ATTNAME: :param Format value: Similar to :ref:`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. .. _qweb-directives-flow: Flow Control ++++++++++++ .. _qweb-directive-set: .. function:: t-set=name (t-value=value | BODY) :param Name name: :param Expression value: :param BODY: 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. .. _qweb-directive-if: .. function:: t-if=condition :param Expression condition: Evaluates ``condition``, suppresses the output of the holder element and its content of the result is falsy. .. _qweb-directive-foreach: .. function:: t-foreach=iterable [t-as=name] :param Expression iterable: :param Name name: 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, :ref:`t-foreach ` adds a number of variables in the context: ``#{name}`` If iterating on an array (or a range), the current value in the iteration. If iterating on an *object*, the current key. ``#{name}_all`` The collection being iterated (the array generated for a ``Number``) ``#{name}_value`` The current iteration value (current item for an array, value for the current item for an object) ``#{name}_index`` The 0-based index of the current iteration round. ``#{name}_first`` Whether the current iteration round is the first one. ``#{name}_parity`` ``"odd"`` if the current iteration round is odd, ``"even"`` otherwise. ``0`` is considered even. .. _qweb-directive-call: .. function:: t-call=template [BODY] :param String template: :param BODY: 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 `_. .. _qweb-directives-inheritance: Template Inheritance and Extension ++++++++++++++++++++++++++++++++++ .. _qweb-directive-extend: .. function:: t-extend=template BODY :param String template: 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 :ref:`t-name ` will create a new template using the old one as a base. ``BODY`` should be a sequence of :ref:`t-jquery ` alteration directives. .. note:: The inheritance in the second form is *static*: the parent template is copied and transformed when :ref:`t-extend ` is called. If it is altered later (by a :ref:`t-extend ` without a :ref:`t-name `), these changes will *not* appear in the "child" templates. .. _qweb-directive-jquery: .. function:: t-jquery=selector [t-operation=operation] BODY :param String selector: a CSS selector into the parent template :param operation: one of ``append``, ``prepend``, ``before``, ``after``, ``inner`` or ``replace``. :param BODY: ``operation`` argument, or alterations to perform * 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:``. Escape Hatches / debugging ++++++++++++++++++++++++++ .. _qweb-directive-log: .. function:: t-log=expression :param Expression expression: Evaluates the provided expression (in the current template context) and logs its result via ``console.log``. .. _qweb-directive-debug: .. function:: t-debug Injects a debugger breakpoint (via the ``debugger;`` statement) in the compiled template output. .. _qweb-directive-js: .. function:: t-js=context BODY :param Name context: :param BODY: javascript code Injects the provided ``BODY`` javascript code into the compiled template, passing it the current template context using the name specified by ``context``.