Using client-side QWeb templates

Just as it's a bad pattern to programmatically create HTML code in controllers, you should create only the minimum amount of DOM elements in your client side JavaScript code. Fortunately, there's a templating engine available for the client side too and, even more fortunately, it's just the same as for server side code.

We'll use Qweb to make the module from the previous recipe, Create custom widgets, more modular by moving the DOM element creation to QWeb.

Getting ready

This recipe is just a modified version of the previous recipe, Create custom widgets, code, so grab a copy of it and use it to create the module ch15_r02.

How to do it...

We add the QWeb definition in the manifest and change the JavaScript code to use it:

  1. Remove the entire function start from your JavaScript code in static/src/js/ch15_r02.js, but add a member called template:
        var FieldMany2OneButtons = form_common.AbstractField.extend({
            template: 'FieldMany2OneButtons',
  2. Add the template file in static/src/xml/ch15_r02.xml:
    <templates>
        <t t-name="FieldMany2OneButtons">
            <div class="oe_form_field_many2one_buttons">
                <t t-foreach="widget.user_list" t-as="user_id">
                    <button
                        t-att-disabled="widget.get('effective_readonly') ? 'disabled' : False"
                        t-att-data-id="user_id" class="btn btn-default btn-sm"
                    >
                        <t t-esc="widget.user_list[user_id].name" />
                    </button>
                </t>
            </div>
        </t>
    </templates>
  3. Register the QWeb file in your manifest:
        "qweb": [
            'static/src/xml/ch15_r02.xml',
        ],

Now other addons have a much easier time changing the HTML code our widget uses, because they can simply override it with the usual QWeb patterns.

How it works...

As there is already a comprehensive discussion of the basics of QWeb in the Chapter 14, CMS Website Development, recipe Creating or modifying templates: QWeb, we'll focus on what is different here. First of all, you need to realize that we're dealing with the JavaScript QWeb implementation here as opposed to the Python implementation on the server side. This means that you don't have access to browse records or the environment; you only have access to the current widget via variable widget and some helper objects like datetime with a subset of Python as described in the Chapter 8, Backend Views, recipe Passing parameters to forms and actions: Context.

This means that you should have all the intelligence in the widget's JavaScript code and have your template only access properties, or possibly functions, on the widget. Fortunately, the original version of our widget does this already, so the only thing we have to do is to iterate through the object we prepared in init and create buttons accordingly. Given that we can also call all functions available on the widget, we can simply ask it if it should behave as read-only by calling the get function, which returns properties saved before via PropertiesMixin's (defined in web.mixins) set function.

As client side QWeb has nothing to do with QWeb views, there's a different mechanism to make those templates known to the web client; add them via the key qweb to your addon's manifest in a list of file names relative to the addon's root.

There's more...

The reason for making the effort to use QWeb here was extensibility and this is the second big difference between client side and server side Qweb. On the client side, you can't use Xpath expressions, but you need to use jQuery selectors and operations. If we, for example, want to change our widget in yet another module, we'd use the following code to have each of our buttons show a user icon before the user's name:

<t t-extend="FieldMany2OneButtons">
    <t t-jquery="button" t-operation="prepend">
        <i class="fa fa-user" />
    </t>
</t>

If we also gave a t-name attribute here, we'd have made a copy of the original template and left that one untouched. Other possible values for the t-operation attribute are append, before, after, inner and replace, which cause the content of the t element to be either appended to the content of the matched element, put before or after the matched element, replace the content of the matched element (inner), or replace the complete element (replace). There's also t-operation='attributes', which allows you to set an attribute on the matches element, following the same rules as server-side QWeb.

Another tacit difference is that names in client side QWeb are not namespaced by the module name, so you have to choose names for your templates which are probably unique over all addons you install, which is why developers tend to choose rather long names.

See also

The client side QWeb engine has less convenient error messages and handling than other parts of Odoo. A small error often means that simply nothing happens and it's hard for beginners to continue from there. Fortunately, there are some debug statements for client side QWeb templates described later in the chapter, in the recipe Debugging your client side code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.197.213