diff -r 98a84761634f -r 7e69ecc9fd43 src/source/dev_guide/new-form.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/source/dev_guide/new-form.rst Mon Dec 17 17:19:35 2018 +0100 @@ -0,0 +1,129 @@ +.. _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 + + + +