.. _newform: Understanding PyAMS form ======================== The forms are based on ZC3.form framework. It provide HTML and Json .. seealso:: https://z3cform.readthedocs.io/en/latest/ .. _formhowto: How to create a form to a component ----------------------------------- The standard form creation with Z3C is described in the following link. https://z3cform.readthedocs.io/en/latest/mustread/form.html 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 ^^^^^^^^^^^ .. code-block:: python @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. .. code-block:: python 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 ^^^^^^^^^^^^ .. code-block:: python @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