How do I use Formlib?
(Part of ZopeInAnger)
Forms are web components that use widgets to display and input data. Typically a template displays the widgets by accessing an attribute or method on an underlying class. With ZOPE3 forms use schema/interface definitions that get exposed through a webform. You can have does done almost automatically - which is very convenient for when creating objects.
Say you have a ZOPE schema defined in IPeriod? you can create an edit form by something like:
class PeriodEditForm(form.EditForm):
form_fields=form.Fields(IPeriod).omit('__name__','__parent__','name')
add a ZCML entry:
<!-- Edit a period --> <browser:page for="finance.interfaces.IPeriod" class="finance.browser.forms.edit.PeriodEditForm" name="index.html" permission="finance.Office" menu="zmi_views" title="Edit period" />
In a similar fashion an form.AddForm? can be created, adding a create method:
class PeriodAddForm(form.AddForm):
form_fields=form.Fields(IPeriod).omit('__name__','__parent__')
def create(self, data):
logger.info('Creating new period with name %s',data['name'])
self.context.contentName=data['name']
p = Period()
form.applyChanges(p, self.form_fields, data)
return p
When you want to change the behaviour of the forms formlib allows for overriding methods in your form class. These methods are:
def __init__(self,context,request): """ Initialise class variable using the HTTP request information """ # def __call__(self): # """ # When __call__ is defined it overrides the other methods # """ def update(self): """ Called by formlib after __init__ for every page update. This is the method you can use to update form fields from your class """ # def render(self): # """ # Called by formlib after 'update' - returns a rendered page # """
Moreover with class methods you can define formlib behaviour when the user hit the submit button - showing form errors etc. - and fetching field contents creating an onsubmit handler.
(from http://www.nabble.com/Sending-data-to-widgets-t1467934.html) You can implement a custom setUpWidgets method (documented in IFormBaseCustomization? from zope.formlib.interfaces). The default one for edit forms looks like this:
def setUpWidgets(self, ignore_request=False):
self.adapters = {}
self.widgets = setUpEditWidgets(
self.form_fields, self.prefix, self.context, self.request,
adapters=self.adapters, ignore_request=ignore_request
)
setUpEditWidgets (defined in zope.formlib.form) will take the widget's default values from self.context. For example, you could pass in something other than that (perhaps an object holding the data you want the widgets to present). You just have to make sure that it also provides the interface that you're generating the form from.
Current documentation can be found in the formlib form.txt file, sitting in the ZOPE source tree. Have a look at that for some engineering info. One link is at: http://svn.zope.org/zope.formlib/trunk/src/zope/formlib/form.txt
Please modify this page to make it better!
... --philikon, Wed, 03 Jan 2007 04:47:18 -0800 reply
Actually, the second part here is a bit misleading. Add forms are supposed to provide a 'create' method. General stuff that's customizable is specified by the IFormBaseCustomization? interface.
