[Checkins] SVN: z3c.form/trunk/ - Feature: Implemented groups
within forms. Groups allow you to combine a set
Stephan Richter
srichter at cosmos.phy.tufts.edu
Tue Jun 26 18:35:09 EDT 2007
Log message for revision 77114:
- Feature: Implemented groups within forms. Groups allow you to combine a set
of fields/widgets into a logical unit. They were designed with ease of use
in mind.
Changed:
U z3c.form/trunk/CHANGES.txt
U z3c.form/trunk/setup.py
U z3c.form/trunk/src/z3c/form/README.txt
U z3c.form/trunk/src/z3c/form/form.py
A z3c.form/trunk/src/z3c/form/group.py
A z3c.form/trunk/src/z3c/form/group.txt
U z3c.form/trunk/src/z3c/form/interfaces.py
U z3c.form/trunk/src/z3c/form/subform.txt
A z3c.form/trunk/src/z3c/form/tests/simple_groupedit.pt
U z3c.form/trunk/src/z3c/form/tests/test_doc.py
-=-
Modified: z3c.form/trunk/CHANGES.txt
===================================================================
--- z3c.form/trunk/CHANGES.txt 2007-06-26 20:36:26 UTC (rev 77113)
+++ z3c.form/trunk/CHANGES.txt 2007-06-26 22:35:05 UTC (rev 77114)
@@ -2,6 +2,14 @@
CHANGES
=======
+Version 1.4.0 (??/??/2007)
+-------------------------
+
+- Feature: Implemented groups within forms. Groups allow you to combine a set
+ of fields/widgets into a logical unit. They were designed with ease of use
+ in mind.
+
+
Version 1.3.0 (6/22/2007)
-------------------------
Modified: z3c.form/trunk/setup.py
===================================================================
--- z3c.form/trunk/setup.py 2007-06-26 20:36:26 UTC (rev 77113)
+++ z3c.form/trunk/setup.py 2007-06-26 22:35:05 UTC (rev 77114)
@@ -27,6 +27,7 @@
[read('src', 'z3c', 'form', name)
for name in ('README.txt',
'form.txt',
+ 'group.txt',
'subform.txt',
'field.txt',
'button.txt',
@@ -42,7 +43,7 @@
setup (
name='z3c.form',
- version='1.3.0',
+ version='1.4.0',
author = "Stephan Richter, Roger Ineichen and the Zope Community",
author_email = "zope3-dev at zope.org",
description = "An advanced form and widget framework for Zope 3",
Modified: z3c.form/trunk/src/z3c/form/README.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/README.txt 2007-06-26 20:36:26 UTC (rev 77113)
+++ z3c.form/trunk/src/z3c/form/README.txt 2007-06-26 22:35:05 UTC (rev 77114)
@@ -12,6 +12,11 @@
Describes the setup and usage of forms in the most common usages. Some
details are provided to the structure of form components.
+- ``group.txt`` [must read]
+
+ This document describes how widget groups are implemented within this
+ package and how they can be used.
+
- ``subform.txt`` [must read]
Introduces the complexities surrounding sub-forms and details two classes of
Modified: z3c.form/trunk/src/z3c/form/form.py
===================================================================
--- z3c.form/trunk/src/z3c/form/form.py 2007-06-26 20:36:26 UTC (rev 77113)
+++ z3c.form/trunk/src/z3c/form/form.py 2007-06-26 22:35:05 UTC (rev 77114)
@@ -77,17 +77,25 @@
template = None
def getContent(self):
+ '''See interfaces.IForm'''
return self.context
def updateWidgets(self):
+ '''See interfaces.IForm'''
self.widgets = zope.component.getMultiAdapter(
(self, self.request, self.getContent()), interfaces.IWidgets)
self.widgets.update()
+ def extractData(self):
+ '''See interfaces.IForm'''
+ return self.widgets.extract()
+
def update(self):
+ '''See interfaces.IForm'''
self.updateWidgets()
def render(self):
+ '''See interfaces.IForm'''
# render content template
if self.template is None:
template = zope.component.getMultiAdapter((self, self.request),
@@ -154,7 +162,7 @@
@button.buttonAndHandler(_('Add'), name='add')
def handleAdd(self, action):
- data, errors = self.widgets.extract()
+ data, errors = self.extractData()
if errors:
self.status = self.formErrorsMessage
return
@@ -209,7 +217,7 @@
@button.buttonAndHandler(_('Apply'), name='apply')
def handleApply(self, action):
- data, errors = self.widgets.extract()
+ data, errors = self.extractData()
if errors:
self.status = self.formErrorsMessage
return
Added: z3c.form/trunk/src/z3c/form/group.py
===================================================================
--- z3c.form/trunk/src/z3c/form/group.py (rev 0)
+++ z3c.form/trunk/src/z3c/form/group.py 2007-06-26 22:35:05 UTC (rev 77114)
@@ -0,0 +1,85 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Widget Group Implementation
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import zope.interface
+
+from z3c.form import form, interfaces
+
+class Group(form.BaseForm):
+
+ label = None
+
+ def __init__(self, context, request, parentForm):
+ self.context = context
+ self.request = request
+ self.parentForm = self.__parent__ = parentForm
+
+ def updateWidgets(self):
+ '''See interfaces.IForm'''
+ self.widgets = zope.component.getMultiAdapter(
+ (self, self.request, self.getContent()), interfaces.IWidgets)
+ for attrName in ('mode', 'ignoreRequest', 'ignoreContext',
+ 'ignoreReadonly'):
+ value = getattr(self.parentForm.widgets, attrName)
+ setattr(self.widgets, attrName, value)
+ self.widgets.update()
+
+
+
+class GroupForm(object):
+ """A mix-in class for add and edit forms to support groups."""
+
+ groups = ()
+
+ def extractData(self):
+ '''See interfaces.IForm'''
+ data, errors = super(GroupForm, self).extractData()
+ for group in self.groups:
+ groupData, groupErrors = group.extractData()
+ data.update(groupData)
+ if groupErrors:
+ if errors:
+ errors += groupErrors
+ else:
+ errors = groupErrors
+ return data, errors
+
+ def applyChanges(self, data):
+ '''See interfaces.IEditForm'''
+ changed = False
+ content = self.getContent()
+ form.applyChanges(self, content, data)
+ for group in self.groups:
+ groupChanged = form.applyChanges(group, content, data)
+ changed = changed or groupChanged
+ if changed:
+ zope.event.notify(
+ zope.lifecycleevent.ObjectModifiedEvent(content))
+ return changed
+
+ def update(self):
+ '''See interfaces.IForm'''
+ self.updateWidgets()
+ groups = []
+ for groupClass in self.groups:
+ group = groupClass(self.context, self.request, self)
+ group.update()
+ groups.append(group)
+ self.groups = tuple(groups)
+ self.updateActions()
+ self.actions.execute()
Property changes on: z3c.form/trunk/src/z3c/form/group.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: z3c.form/trunk/src/z3c/form/group.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/group.txt (rev 0)
+++ z3c.form/trunk/src/z3c/form/group.txt 2007-06-26 22:35:05 UTC (rev 77114)
@@ -0,0 +1,425 @@
+===========
+Group Forms
+===========
+
+Group forms allow you to split up a form into several logical units without
+much overhead. To the parent form, groups should be only dealt with during
+coding and be transparent on the data extraction level.
+
+For the examples to work, we have to bring up most of the form framework:
+
+ >>> from z3c.form import testing
+ >>> testing.setupFormDefaults()
+
+So let's first define a complex content component that warrants setting up
+multiple groups:
+
+ >>> import zope.interface
+ >>> import zope.schema
+
+ >>> class IVehicleRegistration(zope.interface.Interface):
+ ... firstName = zope.schema.TextLine(title=u'First Name')
+ ... lastName = zope.schema.TextLine(title=u'Last Name')
+ ...
+ ... license = zope.schema.TextLine(title=u'License')
+ ... address = zope.schema.TextLine(title=u'Address')
+ ...
+ ... model = zope.schema.TextLine(title=u'Model')
+ ... make = zope.schema.TextLine(title=u'Make')
+ ... year = zope.schema.Int(title=u'Year')
+
+ >>> class VehicleRegistration(object):
+ ... zope.interface.implements(IVehicleRegistration)
+ ...
+ ... def __init__(self, **kw):
+ ... for name, value in kw.items():
+ ... setattr(self, name, value)
+
+The schema above can be separated into basic, license, and car information,
+where the latter two will be placed into groups. First we create the two
+groups:
+
+ >>> from z3c.form import field, group
+
+ >>> class LicenseGroup(group.Group):
+ ... label = u'License'
+ ... fields = field.Fields(IVehicleRegistration).select(
+ ... 'license', 'address')
+
+ >>> class CarGroup(group.Group):
+ ... label = u'Car'
+ ... fields = field.Fields(IVehicleRegistration).select(
+ ... 'model', 'make', 'year')
+
+Most of the group is setup like any other (sub)form. Additionally, you can
+specify a label, which is a human-readable string that can be used for layout
+purposes.
+
+Let's now create an add form for the entire vehicle registration. In
+comparison to a regular add form, you only need to add the ``GroupForm`` as
+one of the base classes. The groups are specified in a simple tuple:
+
+ >>> import os
+ >>> from zope.app.pagetemplate import viewpagetemplatefile
+ >>> from z3c.form import form, tests
+
+ >>> class RegistrationAddForm(group.GroupForm, form.AddForm):
+ ... fields = field.Fields(IVehicleRegistration).select(
+ ... 'firstName', 'lastName')
+ ... groups = (LicenseGroup, CarGroup)
+ ...
+ ... template = viewpagetemplatefile.ViewPageTemplateFile(
+ ... 'simple_groupedit.pt', os.path.dirname(tests.__file__))
+ ...
+ ... def create(self, data):
+ ... return VehicleRegistration(**data)
+ ...
+ ... def add(self, object):
+ ... self.getContent()['obj1'] = object
+ ... return object
+
+
+Note: The order of the base classes is very important here. The ``GroupForm``
+class must be left of the ``AddForm`` class, because the ``GroupForm`` class
+overrides some methods of the ``AddForm`` class.
+
+Now we can instantiate the form:
+
+ >>> request = testing.TestRequest()
+
+ >>> add = RegistrationAddForm(None, request)
+ >>> add.update()
+
+After the form is updated the tuple of group classes is converted to group
+instances:
+
+ >>> add.groups
+ (<LicenseGroup object at ...>, <CarGroup object at ...>)
+
+We can now render the form:
+
+ >>> print add.render()
+ <html>
+ <body>
+ <form action=".">
+ <div class="row">
+ <label for="form-widgets-firstName">First Name</label>
+ <input type="text" id="form-widgets-firstName"
+ name="form.widgets.firstName" class="textWidget"
+ value="" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-lastName">Last Name</label>
+ <input type="text" id="form-widgets-lastName"
+ name="form.widgets.lastName" class="textWidget"
+ value="" />
+ </div>
+ <fieldgroup>
+ <legend>License</legend>
+ <div class="row">
+ <label for="form-widgets-license">License</label>
+ <input type="text" id="form-widgets-license"
+ name="form.widgets.license" class="textWidget"
+ value="" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-address">Address</label>
+ <input type="text" id="form-widgets-address"
+ name="form.widgets.address" class="textWidget"
+ value="" />
+ </div>
+ </fieldgroup>
+ <fieldgroup>
+ <legend>Car</legend>
+ <div class="row">
+ <label for="form-widgets-model">Model</label>
+ <input type="text" id="form-widgets-model"
+ name="form.widgets.model" class="textWidget" value="" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-make">Make</label>
+ <input type="text" id="form-widgets-make"
+ name="form.widgets.make" class="textWidget" value="" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-year">Year</label>
+ <input type="text" id="form-widgets-year"
+ name="form.widgets.year" class="textWidget" value="" />
+ </div>
+ </fieldgroup>
+ <div class="action">
+ <input type="submit" id="form-buttons-add"
+ name="form.buttons.add" class="submitWidget"
+ value="Add" />
+ </div>
+ </form>
+ </body>
+ </html>
+
+Let's now submit the form, but forgetting to enter the address:
+
+ >>> request = testing.TestRequest(form={
+ ... 'form.widgets.firstName': u'Stephan',
+ ... 'form.widgets.lastName': u'Richter',
+ ... 'form.widgets.license': u'MA 40387',
+ ... 'form.widgets.model': u'BMW',
+ ... 'form.widgets.make': u'325',
+ ... 'form.widgets.year': u'2005',
+ ... 'form.buttons.add': u'Add'
+ ... })
+
+ >>> add = RegistrationAddForm(None, request)
+ >>> add.update()
+ >>> print add.render()
+ <html>
+ <body>
+ <i>There were some errors.</i>
+ <form action=".">
+ ...
+ <fieldgroup>
+ <legend>License</legend>
+ <ul>
+ <li>
+ Address: <div class="error">Required input is missing.</div>
+ </li>
+ </ul>
+ ...
+ </fieldgroup>
+ ...
+ </form>
+ </body>
+ </html>
+
+As you can see, the template is clever enough to just report the errors at the
+top of the form, but still report the actual problem within the group. So what
+happens, if errors happen inside and outside a group?
+
+ >>> request = testing.TestRequest(form={
+ ... 'form.widgets.firstName': u'Stephan',
+ ... 'form.widgets.license': u'MA 40387',
+ ... 'form.widgets.model': u'BMW',
+ ... 'form.widgets.make': u'325',
+ ... 'form.widgets.year': u'2005',
+ ... 'form.buttons.add': u'Add'
+ ... })
+
+ >>> add = RegistrationAddForm(None, request)
+ >>> add.update()
+ >>> print add.render()
+ <html>
+ <body>
+ <i>There were some errors.</i>
+ <ul>
+ <li>
+ Last Name: <div class="error">Required input is missing.</div>
+ </li>
+ </ul>
+ <form action=".">
+ ...
+ <fieldgroup>
+ <legend>License</legend>
+ <ul>
+ <li>
+ Address: <div class="error">Required input is missing.</div>
+ </li>
+ </ul>
+ ...
+ </fieldgroup>
+ ...
+ </form>
+ </body>
+ </html>
+
+Let's now successfully complete the add form.
+
+ >>> from zope.app.container import btree
+ >>> context = btree.BTreeContainer()
+
+ >>> request = testing.TestRequest(form={
+ ... 'form.widgets.firstName': u'Stephan',
+ ... 'form.widgets.lastName': u'Richter',
+ ... 'form.widgets.license': u'MA 40387',
+ ... 'form.widgets.address': u'10 Main St, Maynard, MA',
+ ... 'form.widgets.model': u'BMW',
+ ... 'form.widgets.make': u'325',
+ ... 'form.widgets.year': u'2005',
+ ... 'form.buttons.add': u'Add'
+ ... })
+
+ >>> add = RegistrationAddForm(context, request)
+ >>> add.update()
+
+The object is now added to the container and all attributes should be set:
+
+ >>> reg = context['obj1']
+ >>> reg.firstName
+ u'Stephan'
+ >>> reg.lastName
+ u'Richter'
+ >>> reg.license
+ u'MA 40387'
+ >>> reg.address
+ u'10 Main St, Maynard, MA'
+ >>> reg.model
+ u'BMW'
+ >>> reg.make
+ u'325'
+ >>> reg.year
+ 2005
+
+Let's now have a look at an edit form for the vehicle registration:
+
+ >>> class RegistrationEditForm(group.GroupForm, form.EditForm):
+ ... fields = field.Fields(IVehicleRegistration).select(
+ ... 'firstName', 'lastName')
+ ... groups = (LicenseGroup, CarGroup)
+ ...
+ ... template = viewpagetemplatefile.ViewPageTemplateFile(
+ ... 'simple_groupedit.pt', os.path.dirname(tests.__file__))
+
+ >>> request = testing.TestRequest()
+
+ >>> edit = RegistrationEditForm(reg, request)
+ >>> edit.update()
+
+After updating the form, we can render the HTML:
+
+ >>> print edit.render()
+ <html>
+ <body>
+ <form action=".">
+ <div class="row">
+ <label for="form-widgets-firstName">First Name</label>
+ <input type="text" id="form-widgets-firstName"
+ name="form.widgets.firstName" class="textWidget"
+ value="Stephan" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-lastName">Last Name</label>
+ <input type="text" id="form-widgets-lastName"
+ name="form.widgets.lastName" class="textWidget"
+ value="Richter" />
+ </div>
+ <fieldgroup>
+ <legend>License</legend>
+ <div class="row">
+ <label for="form-widgets-license">License</label>
+ <input type="text" id="form-widgets-license"
+ name="form.widgets.license" class="textWidget"
+ value="MA 40387" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-address">Address</label>
+ <input type="text" id="form-widgets-address"
+ name="form.widgets.address" class="textWidget"
+ value="10 Main St, Maynard, MA" />
+ </div>
+ </fieldgroup>
+ <fieldgroup>
+ <legend>Car</legend>
+ <div class="row">
+ <label for="form-widgets-model">Model</label>
+ <input type="text" id="form-widgets-model"
+ name="form.widgets.model" class="textWidget"
+ value="BMW" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-make">Make</label>
+ <input type="text" id="form-widgets-make"
+ name="form.widgets.make" class="textWidget"
+ value="325" />
+ </div>
+ <div class="row">
+ <label for="form-widgets-year">Year</label>
+ <input type="text" id="form-widgets-year"
+ name="form.widgets.year" class="textWidget"
+ value="2005" />
+ </div>
+ </fieldgroup>
+ <div class="action">
+ <input type="submit" id="form-buttons-apply"
+ name="form.buttons.apply" class="submitWidget"
+ value="Apply" />
+ </div>
+ </form>
+ </body>
+ </html>
+
+The behavior when an error occurs is identical to that of the add form:
+
+ >>> request = testing.TestRequest(form={
+ ... 'form.widgets.firstName': u'Stephan',
+ ... 'form.widgets.lastName': u'Richter',
+ ... 'form.widgets.license': u'MA 40387',
+ ... 'form.widgets.model': u'BMW',
+ ... 'form.widgets.make': u'325',
+ ... 'form.widgets.year': u'2005',
+ ... 'form.buttons.apply': u'Apply'
+ ... })
+
+ >>> edit = RegistrationEditForm(reg, request)
+ >>> edit.update()
+ >>> print edit.render()
+ <html>
+ <body>
+ <i>There were some errors.</i>
+ <form action=".">
+ ...
+ <fieldgroup>
+ <legend>License</legend>
+ <ul>
+ <li>
+ Address: <div class="error">Required input is missing.</div>
+ </li>
+ </ul>
+ ...
+ </fieldgroup>
+ ...
+ </form>
+ </body>
+ </html>
+
+Let's now complete the form successfully:
+
+ >>> request = testing.TestRequest(form={
+ ... 'form.widgets.firstName': u'Stephan',
+ ... 'form.widgets.lastName': u'Richter',
+ ... 'form.widgets.license': u'MA 4038765',
+ ... 'form.widgets.address': u'11 Main St, Maynard, MA',
+ ... 'form.widgets.model': u'Ford',
+ ... 'form.widgets.make': u'F150',
+ ... 'form.widgets.year': u'2006',
+ ... 'form.buttons.apply': u'Apply'
+ ... })
+
+ >>> edit = RegistrationEditForm(reg, request)
+ >>> edit.update()
+
+The success message will be shown on the form, ...
+
+ >>> print edit.render()
+ <html>
+ <body>
+ <i>Data successfully updated.</i>
+ ...
+ </body>
+ </html>
+
+and the data is correctly updated:
+
+ >>> reg.firstName
+ u'Stephan'
+ >>> reg.lastName
+ u'Richter'
+ >>> reg.license
+ u'MA 4038765'
+ >>> reg.address
+ u'11 Main St, Maynard, MA'
+ >>> reg.model
+ u'Ford'
+ >>> reg.make
+ u'F150'
+ >>> reg.year
+ 2006
+
+And that's
Property changes on: z3c.form/trunk/src/z3c/form/group.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: z3c.form/trunk/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/trunk/src/z3c/form/interfaces.py 2007-06-26 20:36:26 UTC (rev 77113)
+++ z3c.form/trunk/src/z3c/form/interfaces.py 2007-06-26 22:35:05 UTC (rev 77114)
@@ -582,11 +582,28 @@
default=None,
required=False)
+ def getContent():
+ '''Return the content to be displayed and/or edited.'''
+ def updateWidgets(self):
+ '''Update the widgets for the form.
+
+ This method is commonly called from the ``update()`` method and is
+ mainly meant to be a hook for subclasses.
+ '''
+
+ def extractData():
+ '''Extract the data of the form.'''
+
+ def update():
+ '''Update the form.'''
+
+ def render():
+ '''Render the form.'''
+
class ISubForm(IForm):
"""A subform."""
-
class IInputForm(zope.interface.Interface):
"""A form that is meant to process the input of the form controls."""
@@ -648,9 +665,6 @@
class IEditForm(IForm):
"""A form to edit data of a component."""
- def getContent():
- """Return the content object to be modified."""
-
def applyChanges(data):
"""Apply the changes to the content component."""
@@ -673,3 +687,20 @@
description=_('A button manager describing the buttons to be used for '
'the form.'),
schema=IButtons)
+
+class IGroup(IForm):
+ """A group of fields/widgets within a form."""
+
+ label = zope.schema.TextLine(
+ title=u'Label',
+ description=u'A test describing the group. Commonly used for the UI.')
+
+
+class IGroupForm(object):
+ """A form that supports groups."""
+
+ groups = zope.schema.Tuple(
+ title=u'Groups',
+ description=(u'Initially a collection of group classes, which are '
+ u'converted to group instances when the form is '
+ u'updated.'))
Modified: z3c.form/trunk/src/z3c/form/subform.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/subform.txt 2007-06-26 20:36:26 UTC (rev 77113)
+++ z3c.form/trunk/src/z3c/form/subform.txt 2007-06-26 22:35:05 UTC (rev 77114)
@@ -306,7 +306,7 @@
<div class="row">
<label for="owner-widgets-license">License</label>
<input type="text" id="owner-widgets-license"
- name="owner.widgets.license" class="textWidget"
+ name="owner.widgets.license" class="textWidget"
value="MA-97097A87" />
</div>
</fieldset>
@@ -486,15 +486,15 @@
easily.
-Context less subform (for Mats)
--------------------------------
+Context-free subforms
+---------------------
-Ok, that was easy. But what about write a form including a subform wihtout a
+Ok, that was easy. But what about write a form including a subform wihtout a
context? Let's show how we can write a form wihtout any concext using the
-sample above. Note, this sample for do not include actions which store the
+sample above. Note, this sample for do not include actions which store the
form input. You can store the values like in any other forms using the forms
-widget method ``self.widgets.extract()`` which will return the form and subform
-input values.
+widget method ``self.widgets.extract()`` which will return the form and
+subform input values.
>>> from z3c.form.interfaces import IWidgets
>>> class OwnerAddForm(form.EditForm):
@@ -502,7 +502,7 @@
... 'simple_owneredit.pt', templatePath)
... fields = field.Fields(IOwner)
... prefix = 'owner'
- ...
+ ...
... def updateWidgets(self):
... self.widgets = zope.component.getMultiAdapter(
... (self, self.request, self.getContent()), IWidgets)
@@ -516,13 +516,13 @@
... template = viewpagetemplatefile.ViewPageTemplateFile(
... 'simple_caredit.pt', templatePath)
... prefix = 'car'
- ...
+ ...
... def updateWidgets(self):
... self.widgets = zope.component.getMultiAdapter(
... (self, self.request, self.getContent()), IWidgets)
... self.widgets.ignoreContext = True
... self.widgets.update()
- ...
+ ...
... def update(self):
... self.owner = OwnerAddForm(None, self.request)
... self.owner.update()
Added: z3c.form/trunk/src/z3c/form/tests/simple_groupedit.pt
===================================================================
--- z3c.form/trunk/src/z3c/form/tests/simple_groupedit.pt (rev 0)
+++ z3c.form/trunk/src/z3c/form/tests/simple_groupedit.pt 2007-06-26 22:35:05 UTC (rev 77114)
@@ -0,0 +1,36 @@
+<html>
+ <body>
+ <i tal:condition="view/status" tal:content="view/status"/>
+ <ul tal:condition="view/widgets/errors"
+ metal:define-macro="errors">
+ <li tal:repeat="error view/widgets/errors">
+ <tal:block replace="error/widget/label"
+ />: <tal:block replace="structure error/render" />
+ </li>
+ </ul>
+ <form action=".">
+ <div class="row"
+ metal:define-macro="rows"
+ tal:repeat="widget view/widgets/values">
+ <b tal:condition="widget/error"
+ tal:content="structure widget/error/render"
+ /><label for=""
+ tal:attributes="for widget/id"
+ tal:content="widget/label" />
+ <input type="text" tal:replace="structure widget/render"
+ /></div>
+ <fieldgroup tal:condition="view/groups|nothing"
+ tal:repeat="view view/groups">
+ <legend tal:condition="view/label"
+ tal:content="view/label">Label</legend>
+ <div metal:use-macro="template/macros/errors" />
+ <div metal:use-macro="template/macros/rows" />
+ </fieldgroup>
+ <div class="action"
+ tal:condition="view/actions|nothing"
+ tal:repeat="action view/actions/values">
+ <input type="submit" tal:replace="structure action/render"
+ /></div>
+ </form>
+ </body>
+</html>
Property changes on: z3c.form/trunk/src/z3c/form/tests/simple_groupedit.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: z3c.form/trunk/src/z3c/form/tests/test_doc.py
===================================================================
--- z3c.form/trunk/src/z3c/form/tests/test_doc.py 2007-06-26 20:36:26 UTC (rev 77113)
+++ z3c.form/trunk/src/z3c/form/tests/test_doc.py 2007-06-26 22:35:05 UTC (rev 77114)
@@ -85,6 +85,11 @@
optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
),
doctest.DocFileSuite(
+ '../group.txt',
+ setUp=testing.setUp, tearDown=testing.tearDown,
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+ ),
+ doctest.DocFileSuite(
'../subform.txt',
setUp=testing.setUp, tearDown=testing.tearDown,
optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
More information about the Checkins
mailing list