===================
Grouped Form Fields
===================

Rendering forms by just putting out one long list of fields is almost never
usable. The approach taken here is to group fields together and apply styling
via CSS.


Let's define a schema which we will group then:

>>> import zope.interface
>>> import zope.schema
>>>
>>> class IContact(zope.interface.Interface):
...
...     first_name = zope.schema.TextLine(title=u"First name")
...     last_name = zope.schema.TextLine(title=u"Last name")
...     street = zope.schema.TextLine(title=u"Street")
...     city = zope.schema.TextLine(title=u"City")
...     birth_date = zope.schema.Date(title=u"Birth date")
...

Define an add form:

>>> import zope.formlib.form
>>> import gocept.form.grouped
>>> class AddForm(gocept.form.grouped.AddForm):
...
...     field_groups = [
...         gocept.form.grouped.Fields(
...             u'Name', ('first_name', 'last_name'), css_class='class-a'),
...         gocept.form.grouped.Fields(
...             u'Address', ('street', 'city', 'nonexisting'), css_class='class-b'),
...     ]
...
...     form_fields = zope.formlib.form.FormFields(IContact)
...

Notice: The field 'nonexisting' will not cause an error because nonexisting
fields are ignored.

Log in a user:

>>> import zope.security.testing
>>> principal = zope.security.testing.Principal(u'zope.mgr')
>>> participation = zope.security.testing.Participation(principal)
>>> import zope.security.management
>>> zope.security.management.newInteraction(participation)


Instanciate the add form:

>>> import zope.publisher.browser
>>> request = zope.publisher.browser.TestRequest()
>>> request.setPrincipal(principal)
>>> form = AddForm(object(), request)


And render it:

>>> print form.render()
<html>
    ...
    <fieldset class="class-a">
        <legend>Name</legend>
        ...
        ...<input ... name="form.first_name"...
        ...<input ... name="form.last_name"...
        ...
    </fieldset>
    <fieldset class="class-b">
        <legend>Address</legend>
        ...
        ...<input ... name="form.street"...
        ...<input ... name="form.city"...
        ...
    </fieldset>
    <fieldset>
        <legend></legend>
        ...
        ...<input ... name="form.birth_date"...
        ...
    </fieldset>
    ...

>>> zope.security.management.endInteraction()
