tw2.dynforms

tw2.dynforms is a library of widgets for building dynamic forms. The widgets use a combination of client and server logic to allow developers to utilise powerful functionality with ease.

GrowingGridLayout
NamePhone NumberPersonal

A GridLayout that can dynamically grow on the client, with delete and undo functionality. This is useful for allowing users to enter a list of items that can vary in length. To function correctly, the widget must appear inside a CustomisedForm.

  • child
    • Child for this widget. The child must have no id.
  • min_reps
    • Minimum number of repetitions
class DemoGrowingGridLayout(twd.GrowingGridLayout):
    name = twf.TextField()
    phone_number = twf.TextField()
    personal = twf.CheckBox()
<table xmlns:py="http://genshi.edgewall.org/" py:attrs="w.attrs">
    <tr>
        <th py:for="col in w.children[0].children_non_hidden">$col.label</th>
        <td><input style="display:none" type="image" id="${w.compound_id}:undo" src="${w.resources.undo.link}" title="Undo" alt="Undo" onclick="twd_grow_undo(this); return false;"/></td>
    </tr>
    <py:for each="row in w.children">${row.display()}</py:for>
</table>

HidingSingleSelectField
Contact

This widget is a SingleSelectField with additional functionality to hide or show other widgets in the form, depending on the value selected. The widget must be used inside a hiding container, e.g. HidingTableLayout.

  • prompt_text
    • Text to prompt user to select an option.
class DemoHidingSingleSelectField(twd.HidingTableLayout):
    demo_for = twd.HidingSingleSelectField
    contact = twd.HidingSingleSelectField(label_text='Contact method', options=('E-mail', 'Phone', 'SMS'),
        mapping={
            'E-mail': ['email_address'],
            'Phone': ['phone_number'],
            'SMS': ['phone_number'],
        })
    email_address = twf.TextField()
    phone_number = twf.TextField()
<%namespace name="tw" module="tw2.core.mako_util"/>\
<table ${tw.attrs(attrs=w.attrs)}>
   % for i,c in enumerate(w.children_non_hidden):
    <tr class="${(i % 2 and 'even' or 'odd') + (getattr(c, 'required', False) and ' required' or '') + (c.error_msg and ' error' or '')}" \
     %if w.hover_help and c.help_text:
      title="${c.help_text}" \
     %endif
${tw.attrs(attrs=c.container_attrs)} \
id="${c.compound_id or ''}:container">
       % if c.label:
        <th>${c.label}</th>
       % endif
        <td \
       % if not c.label:
colspan="2"\
       % endif
>
            ${c.display() | n}
           % if not w.hover_help:
            ${c.help_text or ''}
           % endif
            <span id="${c.compound_id or ''}:error">${c.error_msg or ''}</span>
        </td>
    </tr>
   % endfor
    <tr class="error"><td colspan="2">
       % for c in w.children_hidden:
        ${c.display() | n}
       % endfor
        <span id="${w.compound_id or ''}:error">${w.error_msg or ''}</span>
    </td></tr>
</table>

HidingCheckBox
Delivery

This widget is a CheckBox with additional functionality to hide or show other widgets in the form, depending on the value selected. The widget must be used inside a hiding container, e.g. HidingTableLayout.

class DemoHidingCheckBox(twd.HidingTableLayout):
    demo_for = twd.HidingCheckBox
    delivery = twd.HidingCheckBox(label_text='Delivery required?', mapping={1:['address']})
    address = twf.TextField()
<%namespace name="tw" module="tw2.core.mako_util"/>\
<table ${tw.attrs(attrs=w.attrs)}>
   % for i,c in enumerate(w.children_non_hidden):
    <tr class="${(i % 2 and 'even' or 'odd') + (getattr(c, 'required', False) and ' required' or '') + (c.error_msg and ' error' or '')}" \
     %if w.hover_help and c.help_text:
      title="${c.help_text}" \
     %endif
${tw.attrs(attrs=c.container_attrs)} \
id="${c.compound_id or ''}:container">
       % if c.label:
        <th>${c.label}</th>
       % endif
        <td \
       % if not c.label:
colspan="2"\
       % endif
>
            ${c.display() | n}
           % if not w.hover_help:
            ${c.help_text or ''}
           % endif
            <span id="${c.compound_id or ''}:error">${c.error_msg or ''}</span>
        </td>
    </tr>
   % endfor
    <tr class="error"><td colspan="2">
       % for c in w.children_hidden:
        ${c.display() | n}
       % endfor
        <span id="${w.compound_id or ''}:error">${w.error_msg or ''}</span>
    </td></tr>
</table>

HidingCheckBoxList
Contact

This widget is a CheckBoxList with additional functionality to hide or show other widgets in the form, depending on the value selected. The widget must be used inside a hiding container, e.g. HidingTableLayout.

  • prompt_text
    • Text to prompt user to select an option.
  • item_validator
    • Validator that applies to each item
class DemoHidingCheckBoxList(twd.HidingTableLayout):
    demo_for = twd.HidingCheckBoxList
    contact = twd.HidingCheckBoxList(label_text='Contact method', options=('E-mail', 'Phone', 'SMS'),
        mapping={
            'E-mail': ['email_address'],
            'Phone': ['phone_number'],
            'SMS': ['phone_number'],
        })
    email_address = twf.TextField()
    phone_number = twf.TextField()
<%namespace name="tw" module="tw2.core.mako_util"/>\
<table ${tw.attrs(attrs=w.attrs)}>
   % for i,c in enumerate(w.children_non_hidden):
    <tr class="${(i % 2 and 'even' or 'odd') + (getattr(c, 'required', False) and ' required' or '') + (c.error_msg and ' error' or '')}" \
     %if w.hover_help and c.help_text:
      title="${c.help_text}" \
     %endif
${tw.attrs(attrs=c.container_attrs)} \
id="${c.compound_id or ''}:container">
       % if c.label:
        <th>${c.label}</th>
       % endif
        <td \
       % if not c.label:
colspan="2"\
       % endif
>
            ${c.display() | n}
           % if not w.hover_help:
            ${c.help_text or ''}
           % endif
            <span id="${c.compound_id or ''}:error">${c.error_msg or ''}</span>
        </td>
    </tr>
   % endfor
    <tr class="error"><td colspan="2">
       % for c in w.children_hidden:
        ${c.display() | n}
       % endfor
        <span id="${w.compound_id or ''}:error">${w.error_msg or ''}</span>
    </td></tr>
</table>

HidingRadioButtonList
Contact

This widget is a RadioButtonList with additional functionality to hide or show other widgets in the form, depending on the value selected. The widget must be used inside a hiding container, e.g. HidingTableLayout.

  • prompt_text
    • Text to prompt user to select an option.
class DemoHidingRadioButtonList(twd.HidingTableLayout):
    demo_for = twd.HidingRadioButtonList
    contact = twd.HidingRadioButtonList(label_text='Contact method', options=('E-mail', 'Phone', 'SMS'),
        mapping={
            'E-mail': ['email_address'],
            'Phone': ['phone_number'],
            'SMS': ['phone_number'],
        })
    email_address = twf.TextField()
    phone_number = twf.TextField()
<%namespace name="tw" module="tw2.core.mako_util"/>\
<table ${tw.attrs(attrs=w.attrs)}>
   % for i,c in enumerate(w.children_non_hidden):
    <tr class="${(i % 2 and 'even' or 'odd') + (getattr(c, 'required', False) and ' required' or '') + (c.error_msg and ' error' or '')}" \
     %if w.hover_help and c.help_text:
      title="${c.help_text}" \
     %endif
${tw.attrs(attrs=c.container_attrs)} \
id="${c.compound_id or ''}:container">
       % if c.label:
        <th>${c.label}</th>
       % endif
        <td \
       % if not c.label:
colspan="2"\
       % endif
>
            ${c.display() | n}
           % if not w.hover_help:
            ${c.help_text or ''}
           % endif
            <span id="${c.compound_id or ''}:error">${c.error_msg or ''}</span>
        </td>
    </tr>
   % endfor
    <tr class="error"><td colspan="2">
       % for c in w.children_hidden:
        ${c.display() | n}
       % endfor
        <span id="${w.compound_id or ''}:error">${w.error_msg or ''}</span>
    </td></tr>
</table>

HidingTableLayout

A TableLayout that can contain hiding widgets.

  • hover_help
    • Whether to display help text as hover tips

HidingListLayout

A ListLayout that can contain hiding widgets.

  • hover_help
    • Whether to display help text as hover tips

CalendarDatePicker
A JavaScript calendar system for picking dates. The date format can be configured on the validator.
  • language
    • Short country code for language to use, e.g. fr, de
class CalendarDatePicker(twf.widgets.InputField):
    """
    A JavaScript calendar system for picking dates. The date format can be configured on the validator.
    """
    resources = [
        twc.CSSLink(modname='tw2.dynforms', filename='static/calendar/calendar-system.css'),
        twc.JSLink(modname='tw2.dynforms', filename='static/calendar/calendar.js'),
        twc.JSLink(modname='tw2.dynforms', filename='static/calendar/calendar-setup.js'),
        twc.Link(id='cal', modname='tw2.dynforms', filename='static/office-calendar.png'),
    ]
    language = twc.Param('Short country code for language to use, e.g. fr, de', default='en')
    show_time = twc.Variable('Whether to display the time', default=False)
    value = twc.Param('The default value is the current date/time', default=None)
    validator = twc.DateValidator
    template = "genshi:tw2.dynforms.templates.calendar"
    type = 'text'
    def prepare(self):
        if not self.value:
            # XXX -- Doing this instead of twc.Deferred consciously.
            # twc.Deferred is/was nice, but the execution in post_define(...) of
            #   cls._deferred = [k for k, v in cls.__dict__.iteritems()
            #                    if isinstance(v, pm.Deferred)]
            # with dir(..) instead of vars(..) is too costly.  This is the only
            # place I'm aware of that actually uses deferred params. - threebean
            self.value = dt.datetime.now()
        super(CalendarDatePicker, self).prepare()
        self.safe_modify('resources')
        self.resources.extend([
            twc.JSLink(parent=self.__class__, modname='tw2.dynforms', filename='static/calendar/lang/calendar-%s.js' % self.language),
        ])
        self.add_call(twc.js_function('Calendar.setup')(dict(
            inputField = self.compound_id,
            ifFormat = self.validator.format,
            button = self.compound_id + ':trigger',
            showsTime = self.show_time
        )))
<div xmlns="http://www.w3.org/1999/xhtml"
     xmlns:py="http://genshi.edgewall.org/">
    <input py:attrs="w.attrs"/>
    <input align="top" type="image" id="${w.compound_id}:trigger" class="date_field_button"
           src="${w.resources.cal.link}" />
</div>

CalendarDateTimePicker
A JavaScript calendar system for picking dates and times.
  • language
    • Short country code for language to use, e.g. fr, de
class CalendarDateTimePicker(CalendarDatePicker):
    """
    A JavaScript calendar system for picking dates and times.
    """
    validator = twc.DateTimeValidator
    show_time = True
<div xmlns="http://www.w3.org/1999/xhtml"
     xmlns:py="http://genshi.edgewall.org/">
    <input py:attrs="w.attrs"/>
    <input align="top" type="image" id="${w.compound_id}:trigger" class="date_field_button"
           src="${w.resources.cal.link}" />
</div>

CustomisedForm

A form that allows specification of several useful client-side behaviours.

  • children
    • Children specified for this widget will be passed to the child
  • id_suffix
    • Suffix to append to compound IDs
  • help_msg
    • This message displays as a div inside the form
  • action
    • URL to submit form data to. If this is None, the form submits to the same URL it was displayed on.
  • method
    • HTTP method used for form submission.
  • submit
    • Submit button widget. If this is None, no submit button is generated.
  • buttons
    • List of additional buttons to be placed at the bottom of the form
  • blank_deleted
    • Blank out any invisible form fields before submitting. This is needed for GrowingGrid.
  • disable_enter
    • Disable the enter button (except with textarea fields). This reduces the chance of users accidentally submitting the form.
  • prevent_multi_submit
    • When the user clicks the submit button, disable it, to prevent the user causing multiple submissions.

CustomisedTableForm
  • id_suffix
    • Suffix to append to compound IDs
  • help_msg
    • This message displays as a div inside the form
  • action
    • URL to submit form data to. If this is None, the form submits to the same URL it was displayed on.
  • method
    • HTTP method used for form submission.
  • submit
    • Submit button widget. If this is None, no submit button is generated.
  • buttons
    • List of additional buttons to be placed at the bottom of the form
  • blank_deleted
    • Blank out any invisible form fields before submitting. This is needed for GrowingGrid.
  • disable_enter
    • Disable the enter button (except with textarea fields). This reduces the chance of users accidentally submitting the form.
  • prevent_multi_submit
    • When the user clicks the submit button, disable it, to prevent the user causing multiple submissions.