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?

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

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"/>

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

Ok, I updated the message accordingly