Forms
Contents
Forms#
Todo
Describe how create forms with Plone's default form framework z3c.form
.
Fields, Widgets, Vocabularies are also described in detail in their own chapters, and will be referenced from examples here.
Plone uses the z3c.form
library to build its web forms.
The packages responsible for integrating z3c.form
with Plone are plone.z3cform
and plone.app.z3cform
, which contain most of the widgets and default templates.
To simplify the process of organizing a form and specifying its widgets and fields, Plone utilizes plone.autoform
, in particular its AutoExtensibleForm
base class.
It is responsible for handling form hints and configuring z3c.form
widgets and groups (fieldsets).
A form is a view that uses these libraries to generate forms.
General forms#
The plonecli provides you with an option to add a form to your Plone package.
Let's assume you created an add-on package with plonecli called collective.awesomeaddon
.
cd collective.awesomeaddon
plonecli add form
After using the plonecli to add a form, you'll have a new sub folder forms
in your package.
Here you will find a configure.zcml
containing the registration of the form.
<!-- ZCML header and other ZCML here -->
<browser:page
name="my-form"
for="*"
class=".my_form.MyForm"
permission="cmf.ManagePortal"
layer="p6.theme5.interfaces.IP6Theme5Layer"
/>
<!-- further ZCML and ZCML footer go inside the `browser:page` node -->
And a Python file with the code.
from plone import schema
from plone.autoform.form import AutoExtensibleForm
from z3c.form import button, form
from zope.interface import Interface
class IMyForm(Interface):
""" Schema Interface for IMyForm
Define your form fields here.
"""
name = schema.TextLine(
title="Your name",
)
class MyForm(AutoExtensibleForm, form.EditForm):
schema = IMyForm
ignoreContext = True
label = "What's your name?"
description = "Simple, sample form"
@button.buttonAndHandler("Ok")
def handleApply(self, action):
data, errors = self.extractData()
if errors:
self.status = self.formErrorsMessage
return
# Do something with valid data here
changes = self.applyChanges(data)
# Set status on this form page
# (this status message is not bind to the session and does not go thru redirects)
if changes:
self.status = "Settings saved"
@button.buttonAndHandler("Cancel")
def handleCancel(self, action):
"""User cancelled. Redirect back to the front page.
"""
Our form MyForm
is a subclass of the z3c.form
base class, z3c.form.form.EditForm
, and plone.autoform.form.AutoExtensibleForm
, which adds some convenient methods to organize the form fields and widgets.
Besides some basic properties such as label
and description
, the more interesting properties are schema
and ignoreContext
.
Configure the form#
In this section, you will configure the form's properties.
schema
#
The schema property points to a schema interface, which defines the fields of our form.
schema = IMyForm
ignoreContext
#
If your form is not bound to an object (such as a Dexterity object), set ignoreContext = True
.
Dexterity add and edit forms#
Dexterity content types come with default add and edit forms. You can build custom add and edit forms to adjust their behavior.
The implementation of the default edit and add forms is in plone.dexterity.browser.edit.py
and plone.dexterity.browser.add.py
.
Todo
Describe Add/Edit forms here and how to customize them. Provide mutiple examples.
Disable form tabbing#
To disable the form tabbing, you have to override the edit and add forms, and provide a property enable_form_tabbing
as False
.
The Python code custom_forms.py
should look like this:
from plone.dexterity.browser import add
from plone.dexterity.browser import edit
from zope.interface import implementer
from zope.interface import Interface
class ICustomEditForm(Interface):
"""
"""
@implementer(ICustomEditForm)
class CustomEditForm(edit.DefaultEditForm):
""" Custom edit form disabling form_tabbing
"""
enable_form_tabbing = False
class ICustomAddForm(Interface):
"""
"""
@implementer(ICustomAddForm)
class CustomAddForm(add.DefaultAddForm):
""" Custom add form disabling form_tabbing
"""
enable_form_tabbing = False
class ICustomAddView(Interface):
""" """
@implementer(ICustomAddView)
class CustomAddView(add.DefaultAddView):
form = CustomAddForm
To activate them, you must override the registration of the forms for your desired content types.
In your configure.zcml
:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
i18n_domain="example.contenttypes">
<!-- Edit form -->
<browser:page
name="edit"
for="example.contenttypes.content.technical_facility.ITechnicalFacility"
class=".custom_forms.CustomEditForm"
permission="cmf.ModifyPortalContent"
layer="example.contenttypes.interfaces.IExampleContenttypesLayer"
/>
<!-- Edit form for TTW CT's -->
<browser:page
name="edit"
for="plone.dexterity.interfaces.IDexterityContainer"
class=".custom_forms.CustomEditForm"
permission="cmf.ModifyPortalContent"
layer="example.contenttypes.interfaces.IExampleContenttypesLayer"
/>
<!-- Add form -->
<adapter
factory=".custom_forms.CustomAddView"
provides="zope.publisher.interfaces.browser.IBrowserPage"
for="Products.CMFCore.interfaces.IFolderish
example.contenttypes.interfaces.IExampleContenttypesLayer
plone.dexterity.interfaces.IDexterityFTI"
name="Technical Facility"
/>
<class class=".custom_forms.CustomAddView">
<require
permission="cmf.AddPortalContent"
interface="zope.publisher.interfaces.browser.IBrowserPage"
/>
</class>
</configure>