How to render a parametrized widget programmatically?

Hi,

I want to render a widget in edit mode in a custom form (simple browser view).

In my view I created therefore this method:

def render_widget(self, name, mode=DISPLAY_MODE):
    fields = api.get_fields(self.context)
    field = fields.get(name)
    if not field:
        return ""
    widget = queryMultiAdapter((field, self.request), IFieldWidget)
    if not widget:
        return ""
    widget.mode = mode
    widget.context = self.context
    alsoProvides(widget, IContextAware)
    widget.update()
    return widget.render()

And this in my template:

<div tal:replace="structure python:view.render_widget('client_contact', 'input')"/>

It renders actually the widget correctly, but the plone.autoform parameters are missing:

directives.widget(
    "client_contact",
    UIDReferenceWidgetFactory,
    catalog="portal_catalog",
    query="get_client_contact_query",
    columns=[
        {
            "name": "getName",
            "width": "50",
            "align": "left",
            "label": _(u"Name"),
        }, {
            "name": "title",
            "width": "50",
            "align": "left",
            "label": _(u"Title"),
        }
    ],
    limit=5,
)

Not exactly sure what I am missing or where to search for it.

Can anyone give me a hint?

Thanks and best regards
Ramon

Hi everyone,

I solved now the problem for me with the following code:

from Products.Five.browser import BrowserView
from plone.autoform.interfaces import WIDGETS_KEY
from zope.component import queryMultiAdapter
from z3c.form.interfaces import IFieldWidget
from z3c.form.interfaces import IContextAware
from zope.interface import alsoProvides

class View(BrowserView):
...
    def render_widget(self, name, mode=DISPLAY_MODE):
        fields = api.get_fields(self.context)
        field = fields.get(name)
        if not field:
            return ""
        widget_tags = field.interface.getTaggedValue(WIDGETS_KEY)
        factory = widget_tags.get(field.getName())
        if factory:
            widget = factory(field, self.request)
        else:
            widget = queryMultiAdapter((field, self.request), IFieldWidget)
        if not widget:
            return ""
        widget.mode = mode
        widget.context = self.context
        alsoProvides(widget, IContextAware)
        widget.update()
        return widget.render()

Please share if you know a more elegant way to achieve this.

Thanks and best regards
Ramon

1 Like