[Welcome] [TitleIndex] [WordIndex

Problem

Quixote's quixote.form2 package generates a user interface automatically. Your code should add widgets to the form and then render the form (call the form's render method).

However, there are some things that you can do to customize the the look of the user interface. This entry suggests several ways to customize the way in which forms and widgets from the quixote.form2 package are rendered.

Solution

Ordering the widgets

Widgets are rendered, from top to bottom, in the same order that you add them to the form. You can change their order by changing the order in which you add them to the form

Adding labels and hints

Use the title argument of the form2.Form.add method to give a widget a title.

Use the hint argument of the form2.Form.add method to give the widget additional user information. The hint is (by default) displayed to the right of the input item.

Here is an example:

    zipForm.add(form2.StringWidget, 'user_name', '[enter user name]',
        title='User name:',
        hint='Enter your name',
        size=40,
        required=False)

Customizing rendering of the form

To customize the way in which the form and the widets in it are rendered, do the following:

  1. Create a subclass of form2.Form.

  2. Override the rendering methods in form2.Form, for example _render_body, _render_sep, and _render_components, _render_start, and _render_finish.

  3. Then create and use an instance of your subclass of form2.Form, instead of form2.Form itself.

Here is an example:

    class MyForm(form2.Form):
        def _render_body(self):
            r = TemplateIO(html=True)
            r += htmltext('<table border="0" width="100%">')
            r += self._render_error_notice()
            r += self._render_components()
            r += self._render_button_widgets()
            r += htmltext('</table>')
            return r.getvalue()

        def render_sep(self):
            return htmltext('<tr><td colspan="3"><hr/></td></tr>')

        def _render_components(self):
            r = TemplateIO(html=True)
            firstTime = True
            for component in self.components:
                if not firstTime:
                    r += self.render_sep()
                firstTime = False
                r += component.render()
            return r.getvalue()

Explanation:

Customizing rendering of the widgets

By default, each widget is rendered in a pair of table rows within an HTML table. We can change this and can change the way in which each widget is rendered by (1) subclassing the class form2.WidgetRow and then (2) instructing the form to use this subclass.

Here is an example in which we render each widget in a single row:

    class MyWidgetRow(form2.WidgetRow):
        def render(self):
            title = self.title or ''
            if title and self.required:
                title = title + htmltext(' *')
            r = TemplateIO(html=True)
            r += htmltext('<tr><th width="15%" align="left">')
            r += title
            r += htmltext('</th><td>')
            r += self.widget.render()
            r += htmltext('</td><td>')
            r += self._render_error()
            r += self._render_hint()
            r += htmltext('</td></tr>')
            return r.getvalue()

Explanation:

Then, we create a form that uses our subclass with something like the following:

    aSimpleForm = form2.Form(name='simple_form',
        action_url='show_contents',
        component_class=MyWidgetRow
        )

Discussion

Here are some links to form2:


2010-09-22 22:14