Understanding PyAMS form

The forms are based on ZC3.form framework. It provide HTML and Json

How to create a form to a component

The standard form creation with Z3C is described in the following link.

PyAMS Form Integration

When creating a new object to the zodb, the construction of the form can’t be based on an object passed context. To build the form we use a default factory that is attached to the container of the element.

1) Add Form

@pagelet_config(name='add-contact-phone-paragraph.html', context=IParagraphContainerTarget, layer=IPyAMSLayer,
                permission=MANAGE_CONTENT_PERMISSION)
class ContactPhoneParagraphAddForm(AdminDialogAddForm):
    """Contact paragraph add form"""

    legend = _("Add new phone contact card")
    dialog_class = 'modal-large'
    icon_css_class = 'fa fa-fw fa-phone'
    edit_permission = MANAGE_CONTENT_PERMISSION

    #Retrieve fields from the interface of the component
    fields = field.Fields(IContactPhoneParagraph).omit('__parent__', '__name__', 'visible')


    def create(self, data):
        """Create one instance of the component"""
        return ContactPhoneParagraph()

    def add(self, object):
        """Add the new component to the container that implement the interface `IParagraphContainer` """
        IParagraphContainer(self.context).append(object)

The associate form field are generated automatically based on this interface attributes

2) Ajax Form

The decorator :py:function:`@ajax_config()` allows the form is working with ajax requests by providing json content.

from pyams_form.form import ajax_config


@pagelet_config(name='add-contact-phone-paragraph.html', context=IParagraphContainerTarget, layer=IPyAMSLayer,
                permission=MANAGE_CONTENT_PERMISSION)
@ajax_config(name='add-contact-phone-paragraph.json', context=IParagraphContainerTarget, layer=IPyAMSLayer,
             base=BaseParagraphAJAXAddForm)
class ContactPhoneParagraphAddForm(AdminDialogAddForm):
    """Contact paragraph add form"""

    legend = _("Add new phone contact card"
            ...

3) Edit form

@adapter_config(context=(IContactPhoneParagraph, IPyAMSLayer), provides=IParagraphInnerEditor)
            permission=MANAGE_CONTENT_PERMISSION)
@ajax_config(name='inner-properties.json', context=IContactPhoneParagraph, layer=IPyAMSLayer,
         base=BaseParagraphAJAXEditForm)
@implementer(IInnerForm)
class ContactPhoneParagraphInnerEditForm(ContactPhoneParagraphPropertiesEditForm):
    """Contact paragraph inner edit form"""

    legend = None

    @property
    def buttons(self):
        if self.mode == INPUT_MODE:
            return button.Buttons(IParagraphEditFormButtons)
        else:
            return button.Buttons()

    def get_ajax_output(self, changes):
        output = super(ContactParagraphInnerAJAXEditForm, self).get_ajax_output(changes)
        updated = changes.get(IBaseParagraph, ())
        if 'title' in updated:
            output.setdefault('events', []).append(get_json_paragraph_refresh_event(self.context, self.request))
        updated = changes.get(IContactParagraph, ())
        if ('photo' in updated) or ('renderer' in updated):
            # we have to commit transaction to be able to handle blobs...
            if 'photo' in updated:
                ITransactionManager(self.context).get().commit()
            output.setdefault('events', []).append(get_json_form_refresh_event(self.context, self.request,
                                                                               ContactParagraphInnerEditForm))
        return output