[Checkins] SVN: z3c.form/trunk/ - Feature: Implemented single
checkbox widget that can be used for boolean
Stephan Richter
srichter at cosmos.phy.tufts.edu
Tue Sep 4 18:32:36 EDT 2007
Log message for revision 79469:
- Feature: Implemented single checkbox widget that can be used for boolean
fields. They are not available by default but can be set using the
``widgetFactory`` attribute.
Changed:
U z3c.form/trunk/CHANGES.txt
U z3c.form/trunk/src/z3c/form/browser/checkbox.py
U z3c.form/trunk/src/z3c/form/browser/checkbox.txt
U z3c.form/trunk/src/z3c/form/configure.zcml
U z3c.form/trunk/src/z3c/form/converter.py
U z3c.form/trunk/src/z3c/form/converter.txt
U z3c.form/trunk/src/z3c/form/interfaces.py
-=-
Modified: z3c.form/trunk/CHANGES.txt
===================================================================
--- z3c.form/trunk/CHANGES.txt 2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/CHANGES.txt 2007-09-04 22:32:36 UTC (rev 79469)
@@ -5,6 +5,10 @@
Version 1.7.0 (9/??/2007)
-------------------------
+- Feature: Implemented single checkbox widget that can be used for boolean
+ fields. They are not available by default but can be set using the
+ ``widgetFactory`` attribute.
+
- Bug: When rendering a widget the ``style`` attribute was not honored. Thanks
to Andreas Reuleaux for reporting.
Modified: z3c.form/trunk/src/z3c/form/browser/checkbox.py
===================================================================
--- z3c.form/trunk/src/z3c/form/browser/checkbox.py 2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/browser/checkbox.py 2007-09-04 22:32:36 UTC (rev 79469)
@@ -21,9 +21,10 @@
import zope.interface
import zope.schema
import zope.schema.interfaces
+from zope.schema import vocabulary
from zope.i18n import translate
-from z3c.form import interfaces
+from z3c.form import interfaces, term
from z3c.form.widget import SequenceWidget, FieldWidget
from z3c.form.browser import widget
@@ -60,3 +61,24 @@
def CheckBoxFieldWidget(field, request):
"""IFieldWidget factory for CheckBoxWidget."""
return FieldWidget(field, CheckBoxWidget(request))
+
+
+class SingleCheckBoxWidget(CheckBoxWidget):
+ """Single Input type checkbox widget implementation."""
+ zope.interface.implementsOnly(interfaces.ISingleCheckBoxWidget)
+
+ klass = u'single-checkbox-widget'
+
+ def updateTerms(self):
+ if self.terms is None:
+ self.terms = term.Terms()
+ self.terms.terms = vocabulary.SimpleVocabulary((
+ vocabulary.SimpleTerm('selected', 'selected', self.label), ))
+ return self.terms
+
+
+ at zope.component.adapter(zope.schema.interfaces.IBool, interfaces.IFormLayer)
+ at zope.interface.implementer(interfaces.IFieldWidget)
+def SingleCheckBoxFieldWidget(field, request):
+ """IFieldWidget factory for CheckBoxWidget."""
+ return FieldWidget(field, SingleCheckBoxWidget(request))
Modified: z3c.form/trunk/src/z3c/form/browser/checkbox.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/browser/checkbox.txt 2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/browser/checkbox.txt 2007-09-04 22:32:36 UTC (rev 79469)
@@ -3,18 +3,18 @@
==============
Note: the checkbox widget isn't registered for a field by default. You can use
-the widgetFactory argument of a IField object if you construct fields or
-set the custom widget factory on selected fields later.
+the ``widgetFactory`` argument of a ``IField`` object if you construct fields
+or set the custom widget factory on selected fields later.
-The CheckBoxWidget renders a checkbox input type field e.g.
-<input type="checkbox" />
+The ``CheckBoxWidget`` widget renders a checkbox input type field e.g. <input
+type="checkbox" />
>>> from zope.interface.verify import verifyClass
>>> from zope.app.form.interfaces import IInputWidget
>>> from z3c.form import interfaces
>>> from z3c.form.browser import checkbox
-The TextWidget is a widget:
+The ``CheckboxWidget`` is a widget:
>>> verifyClass(interfaces.IWidget, checkbox.CheckBoxWidget)
True
@@ -80,7 +80,7 @@
<label for="widget-id-0">
<span class="label">yes</span>
</label>
- </span><span class="option">
+ </span><span class="option">
<input type="checkbox" id="widget-id-1" name="widget.name:list"
class="checkbox-widget" value="false" />
<label for="widget-id-1">
@@ -110,3 +110,70 @@
</label>
</span>
<input name="widget.name-empty-marker" type="hidden" value="1" />
+
+
+Single Checkbox Widget
+----------------------
+
+Instead of using the checkbox widget as an UI component to allow multiple
+selection from a list of choices, it can be also used by itself to toggle a
+selection, effectively making it a binary selector. So in this case it lends
+itself well as a boolean UI input component.
+
+The ``SingleCheckboxWidget`` is a widget:
+
+ >>> verifyClass(interfaces.IWidget, checkbox.SingleCheckBoxWidget)
+ True
+
+The widget can render a input field only by adapting a request:
+
+ >>> request = TestRequest()
+ >>> widget = checkbox.SingleCheckBoxWidget(request)
+
+Set a name and id for the widget:
+
+ >>> widget.id = 'widget-id'
+ >>> widget.name = 'widget.name'
+
+Such a widget provides the ``IWidget`` interface:
+
+ >>> interfaces.IWidget.providedBy(widget)
+ True
+
+For there to be a sensible output, we need to give the widget a label:
+
+ >>> widget.label = u'Do you want that?'
+
+ >>> widget.update()
+ >>> print widget.render()
+ <span class="option">
+ <input type="checkbox" id="widget-id-0"
+ name="widget.name:list"
+ class="single-checkbox-widget" value="selected" />
+ <label for="widget-id-0">
+ <span class="label">Do you want that?</span>
+ </label>
+ </span>
+ <input name="widget.name-empty-marker" type="hidden"
+ value="1" />
+
+Initially, the box is not checked. Changing the widget value to the selection
+value, ...
+
+ >>> widget.value = ['selected']
+
+will make the box checked:
+
+ >>> widget.update()
+ >>> print widget.render()
+ <span class="option">
+ <input type="checkbox" id="widget-id-0"
+ name="widget.name:list"
+ class="single-checkbox-widget" value="selected"
+ checked="checked" />
+ <label for="widget-id-0">
+ <span class="label">Do you want that?</span>
+ </label>
+ </span>
+ <input name="widget.name-empty-marker" type="hidden"
+ value="1" />
Modified: z3c.form/trunk/src/z3c/form/configure.zcml
===================================================================
--- z3c.form/trunk/src/z3c/form/configure.zcml 2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/configure.zcml 2007-09-04 22:32:36 UTC (rev 79469)
@@ -64,6 +64,9 @@
factory=".converter.CollectionSequenceDataConverter"
/>
<adapter
+ factory=".converter.BoolSingleCheckboxDataConverter"
+ />
+ <adapter
factory=".converter.FieldWidgetDataConverter"
/>
Modified: z3c.form/trunk/src/z3c/form/converter.py
===================================================================
--- z3c.form/trunk/src/z3c/form/converter.py 2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/converter.py 2007-09-04 22:32:36 UTC (rev 79469)
@@ -284,3 +284,22 @@
if isinstance(collectionType, tuple):
collectionType = collectionType[-1]
return collectionType([widget.terms.getValue(token) for token in value])
+
+
+class BoolSingleCheckboxDataConverter(BaseDataConverter):
+ "A special converter between boolean fields and single checkbox widgets."
+
+ zope.component.adapts(
+ zope.schema.interfaces.IBool, interfaces.ISingleCheckBoxWidget)
+
+ def toWidgetValue(self, value):
+ """Convert from Python bool to HTML representation."""
+ if value:
+ return ['selected']
+ return []
+
+ def toFieldValue(self, value):
+ """See interfaces.IDataConverter"""
+ if value and value[0] == 'selected':
+ return True
+ return False
Modified: z3c.form/trunk/src/z3c/form/converter.txt
===================================================================
--- z3c.form/trunk/src/z3c/form/converter.txt 2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/converter.txt 2007-09-04 22:32:36 UTC (rev 79469)
@@ -602,3 +602,35 @@
>>> seqWidget.terms
<z3c.form.term.CollectionTerms object ...>
+
+
+Boolean to Single Checkbox Data Converter
+-----------------------------------------
+
+The conversion from any field to the single checkbox widget value is a special
+case, because it has to be defined what selecting the value means. In the case
+of the boolean field, "selected" means ``True`` and if unselected, ``False``
+is returned:
+
+ >>> boolField = zope.schema.Bool()
+
+ >>> bscbx = converter.BoolSingleCheckboxDataConverter(boolField, seqWidget)
+ >>> bscbx
+ <BoolSingleCheckboxDataConverter converts from Bool to SequenceWidget>
+
+Let's now convert boolean field to widget values:
+
+ >>> bscbx.toWidgetValue(True)
+ ['selected']
+ >>> bscbx.toWidgetValue(False)
+ []
+
+Converting back is equally simple:
+
+ >>> bscbx.toFieldValue(['selected'])
+ True
+ >>> bscbx.toFieldValue([])
+ False
+
+Note that this widget has no concept of missing value, since it can only
+represent two states by desgin.
Modified: z3c.form/trunk/src/z3c/form/interfaces.py
===================================================================
--- z3c.form/trunk/src/z3c/form/interfaces.py 2007-09-04 22:18:11 UTC (rev 79468)
+++ z3c.form/trunk/src/z3c/form/interfaces.py 2007-09-04 22:32:36 UTC (rev 79469)
@@ -438,6 +438,9 @@
class ICheckBoxWidget(ISequenceWidget):
"""Checbox widget."""
+class ISingleCheckBoxWidget(ICheckBoxWidget):
+ """Single Checbox widget."""
+
class IRadioWidget(ISequenceWidget):
"""Radio widget."""
More information about the Checkins
mailing list