Search views

When opening your list view, you'll notice the search field to the upper right. If you type something there, you get suggestions about what to search for and there is also a set of predefined filters to choose from. This recipe will walk you through how to define those suggestions and options.

How to do it...

  1. Define your search view:
    <record id="search_all_customers" model="ir.ui.view">
        <field name="model">res.partner</field>
        <field name="arch" type="xml">
            <search>
                <field name="name" />
                <field name="category_id"
                       filter_domain="[('category_id', 'child_of', self)]" />
                <field name="bank_ids" widget="many2one" />
                <filter name="suppliers"
                        string="Suppliers"
                        domain="[('supplier', '=', True)]" />
            </search>
        </field>
    </record>
  2. Tell your action to use it:
    <record id="action_all_customers" model="ir.actions.act_window">
        <field name="name">All customers</field>
        <field name="res_model">res.partner</field>
        <field name="domain">[('customer', '=', True)]</field>
        <field name="search_view_id" ref="search_all_customers" />
    </record>

When you type something in the search bar now, you'll be offered to search for this term in the name, categories, and bank accounts fields. If your term happens to be a substring of a bank account number in your system, you'll even be offered to search exactly for this bank account.

How it works...

In the case of name, we simply listed the field as the one to be offered to the user to search for. We left the semantics at the defaults, which is a substring search for character fields.

For categories, we do something more interesting. By default, your search term applied to a many2many field triggers name_search, which would be a substring search in the categorie's names in this case. But depending on your category structure, it can be very convenient to search for partners who have the category you're interested in or a child of it. Think about a main category Newsletter subscribers with sub categories Weekly newsletter, Monthly newsletter, and a couple of other newsletter types. Searching for newsletter subscribers with the preceding search view definition will give you everyone who is subscribed to any of those newsletters in one go, which is a lot more convenient than searching for every single type and combining the results.

The filter_domain attribute can contain an arbitrary domain, so you're neither restricted to searching for the same field you named in the name attribute, nor to using only one term. The variable self is what the user filled in, and also the only variable you can use here. A more elaborate example from the default search view for partners is:

<field name="name" filter_domain="['|','|',
('display_name','ilike',self),('ref','=',self),('email','ilike',self)]"/>

This allows the user to not even think a lot about what to search for; just type some letters, hit Enter, and, with a bit of luck, one of the fields mentioned contains the string we're looking for.

For the bank_ids field, we used another trick. The type of a field not only decides the default way of searching for the user's input, it also defines the way Odoo presents the suggestions. And given many2one fields are the only ones that offer auto completion, we force Odoo to do that, even though bank_ids is a one2many field by setting the widget attribute. Without this, the offer would be simply to search in this field, without completion suggestions. The same applies to many2many fields. Note that every field with a many2one widget set will trigger a search on its model for every one of the user's keystrokes – don't use too many of them.

You should also put the most used fields to the top, because the first field is what is searched if the user just types something and hits Enter. It also seems worth mentioning that the search bar is very well usable with the keyboard; select a suggestion by pressing the down arrow and open a many2one's completion suggestion by pressing the right arrow. If you educate your users in this and pay attention to a sensible ordering of fields in the search view, they will be much more efficient than by typing something first, grabbing the mouse, and selecting some option.

The filter element creates a button that adds the content of the filter's domain attribute to the search domain. You should add a logical internal name and a string attribute to describe the filter to your users.

There's more...

You can group the filters with the group tag, which causes them to be rendered slightly closer together than the other filters, but this has semantic implications too. If you put multiple filters in the same group and activate more than one of them, their domains will be combined with the operator |, while filters and fields not in the same group are combined with the operator &. Cases where you want disjunction for your filters are when they filter for mutually exclusive sets, in which case selecting both of them always would lead to an empty result set. Within the same group, you can achieve the same effect with the separator element.

Note that if the user fills in multiple queries for the same field, they will be combined with | too, so you don't need to worry about that.

As well as the field, the filter element can have a context attribute whose content will be merged with the current context and eventual other context attributes in the search view. This is essential for views that support grouping (see recipes about kanban and graph views), because the resulting context determines the field(s) to be grouped by with the key group_by. We'll look into the details of grouping in the appropriate recipes, but the context has other uses too. For example, you can hide columns depending on a context value by setting the field element's invisible attribute in the list view to something like the following:

invisible="not context.get('show_col1')"

You can use a filter to switch this column on or off. Or you could write a function field that returns different values depending on the context, then you can change the values by activating a filter.

The search view itself also responds to context keys. In a very similar way to default values when creating records, you can pass defaults for a search view via the context. If we had set a context of {'search_default_supplier': 1} in our previous action, the suppliers filter would have been preselected in the search view. This works only if the filter has a name though, which is why you should always set it. To set defaults for fields in the search view, use search_default_$fieldname.

Further, the field and the filter elements can have a groups property with the same semantics as in the form views in order to make the element only visible for certain groups.

See also

For details about manipulating the context, see the recipe Passing parameters to forms and actions: Context.

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

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