Adding a new widget

I want to add a new custom widget in Sao.

It is pretty easy to add a new one using custom.js (no patch is needed) but the problem is that when I use <field name="x" widget="new_widget"/> tests fail because the form.rng has a strict list of valid widgets.

Has anybody found the same issue? Any ideas on how to solve that? Any ideas on how we could add support for this in trytond?

1 Like

You can override ir.ui.view’s get_rng method to return the one you want.

We’ve been doing this for years, and it works as advertised :slight_smile:

This allows to use a widget named source :

class View(metaclass=PoolMeta):
    __name__ = 'ir.ui.view'

    @classmethod
    @functools.lru_cache(maxsize=10)
    def get_rng(cls, type_):
        rng = super(View, cls).get_rng(type_)
        if type_ in ('form', 'list-form'):
            widgets = rng.xpath(
                '//ns:define/ns:optional/ns:attribute'
                '/ns:name[.="widget"]/following-sibling::ns:choice',
                namespaces={'ns': 'http://relaxng.org/ns/structure/1.0'})[0]
            subelem = etree.SubElement(widgets,
                '{http://relaxng.org/ns/structure/1.0}value')
            subelem.text = 'source'
        return rng
2 Likes

Worked like a charm.

Thanks!

Hi,

Is there any topic to show how to create widget?
or the minimun widget template?

Best regards

Not that I know of but here’s all you need to add a new form widget in sao that can render data returned by a field:

  • Implement the widget in sao implemeting its API as can be seen here.
  • Register the new widget in the WIDGETS dictionary. It can be done in custom.js with: Sao.View.FormXMLViewParser.WIDGETS['mywidget'] = MyFormWidget;
  • Ensure the server also accepts your widget by overriding get_rng:
class View(metaclass=PoolMeta):
    __name__ = 'ir.ui.view'

    @classmethod
    def get_rng(cls, type_):
        rng = super(View, cls).get_rng(type_)
        if type_ in ('form', 'list-form'):
            widgets = rng.xpath(
                '//ns:define/ns:optional/ns:attribute'
                '/ns:name[.="widget"]/following-sibling::ns:choice',
                namespaces={'ns': 'http://relaxng.org/ns/structure/1.0'})[0]
            subelem = etree.SubElement(widgets,
                '{http://relaxng.org/ns/structure/1.0}value')
            subelem.text = 'mywidget'
        return rng

This allows you to use the widget in any form view with <field name="myfield" widget="mywidget"/>

1 Like

I would remove this cache, it can only create trouble for no runtime benefit.

Ok, I updated the message accordingly