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

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') + ((c.validator and getattr(c.validator, 'required', getattr(c.validator, 'not_empty', 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><label for="${c.id}">${c.label}</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

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') + ((c.validator and getattr(c.validator, 'required', getattr(c.validator, 'not_empty', 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><label for="${c.id}">${c.label}</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

    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') + ((c.validator and getattr(c.validator, 'required', getattr(c.validator, 'not_empty', 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><label for="${c.id}">${c.label}</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

    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') + ((c.validator and getattr(c.validator, 'required', getattr(c.validator, 'not_empty', 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><label for="${c.id}">${c.label}</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.