Skip to content

Commit

Permalink
Merge remote-tracking branch 'mmilkin/json-forms'
Browse files Browse the repository at this point in the history
  • Loading branch information
mauritsvanrees committed Feb 1, 2016
2 parents b5a2d0e + 9375484 commit df4c3d0
Show file tree
Hide file tree
Showing 20 changed files with 612 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
This package provides an implementation for HTML forms and widgets. The goal
This package provides an implementation for HTML and JSON forms and widgets. The goal
is to provide a simple API but with the ability to easily customize any data or
steps.
5 changes: 5 additions & 0 deletions src/z3c/form/browser/checkbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ def update(self):
{'id':id, 'name':self.name + ':list', 'value':term.token,
'label':label, 'checked':checked})

def json_data(self):
data = super(CheckBoxWidget, self).json_data()
data['options'] = self.items
data['type'] = 'check'
return data

@zope.component.adapter(zope.schema.interfaces.IField, interfaces.IFormLayer)
@zope.interface.implementer(interfaces.IFieldWidget)
Expand Down
83 changes: 83 additions & 0 deletions src/z3c/form/browser/checkbox.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,28 @@ Now let's try if we get widget values:
</span>
<input name="widget.name-empty-marker" type="hidden" value="1" />

The checkbox json_data representation:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'input',
'name': 'widget.name',
'options': [{'checked': False,
'id': 'widget-id-0',
'label': 'yes',
'name': 'widget.name:list',
'value': 'true'},
{'checked': False,
'id': 'widget-id-1',
'label': 'no',
'name': 'widget.name:list',
'value': 'false'}],
'required': False,
'type': 'check',
'value': ()}

If we set the value for the widget to ``yes``, we can se that the checkbox
field get rendered with a checked flag:

Expand All @@ -114,6 +136,28 @@ field get rendered with a checked flag:
</span>
<input name="widget.name-empty-marker" type="hidden" value="1" />

The checkbox json_data representation:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'input',
'name': 'widget.name',
'options': [{'checked': True,
'id': 'widget-id-0',
'label': 'yes',
'name': 'widget.name:list',
'value': 'true'},
{'checked': False,
'id': 'widget-id-1',
'label': 'no',
'name': 'widget.name:list',
'value': 'false'}],
'required': False,
'type': 'check',
'value': 'true'}

Check HIDDEN_MODE:

>>> template = os.path.join(os.path.dirname(z3c.form.browser.__file__),
Expand All @@ -134,6 +178,28 @@ Check HIDDEN_MODE:
class="checkbox-widget" value="false" />
</span>

The checkbox json_data representation:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'hidden',
'name': 'widget.name',
'options': [{'checked': True,
'id': 'widget-id-0',
'label': 'yes',
'name': 'widget.name:list',
'value': 'true'},
{'checked': False,
'id': 'widget-id-1',
'label': 'no',
'name': 'widget.name:list',
'value': 'false'}],
'required': False,
'type': 'check',
'value': 'true'}

Make sure that we produce a proper label when we have no title for a term and
the value (which is used as a backup label) contains non-ASCII characters:

Expand Down Expand Up @@ -201,6 +267,23 @@ For there to be a sensible output, we need to give the widget a label:
<input name="widget.name-empty-marker" type="hidden"
value="1" />

The checkbox json_data representation:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': 'Do you want that?',
'mode': 'input',
'name': 'widget.name',
'options': [{'checked': False,
'id': 'widget-id-0',
'label': 'Do you want that?',
'name': 'widget.name:list',
'value': 'selected'}],
'required': False,
'type': 'check',
'value': ()}

Initially, the box is not checked. Changing the widget value to the selection
value, ...

Expand Down
5 changes: 5 additions & 0 deletions src/z3c/form/browser/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class FileWidget(text.TextWidget):
headers = None
filename = None

def json_data(self):
data = super(FileWidget, self).json_data()
data['type'] = 'file'
return data


@zope.component.adapter(zope.schema.interfaces.IBytes, interfaces.IFormLayer)
@zope.interface.implementer(interfaces.IFieldWidget)
Expand Down
4 changes: 4 additions & 0 deletions src/z3c/form/browser/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ def extract(self, default=interfaces.NO_VALUE):
'y': int(self.request[self.name + '.y']),
'value': self.request[self.name]}

def json_data(self):
data = super(ImageWidget, self).json_data()
data['type'] = 'image'
return data

@zope.component.adapter(interfaces.IImageButton, interfaces.IFormLayer)
@zope.interface.implementer(interfaces.IFieldWidget)
Expand Down
7 changes: 7 additions & 0 deletions src/z3c/form/browser/orderedselect.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ def deselect(self):
notselecteditems.append(item)
return notselecteditems

def json_data(self):
data = super(OrderedSelectWidget, self).json_data()
data['options'] = self.items
data['selected'] = self.selectedItems
data['notSelected'] = self.notselectedItems
data['type'] = 'multiSelect'
return data

@zope.component.adapter(zope.schema.interfaces.ISequence, interfaces.IFormLayer)
@zope.interface.implementer(interfaces.IFieldWidget)
Expand Down
33 changes: 33 additions & 0 deletions src/z3c/form/browser/orderedselect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,21 @@ If we render the widget we get an empty widget:
</tr>
</table>

The json data representing the oredered select widget:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'input',
'name': 'widget.name',
'notSelected': (),
'options': (),
'required': False,
'selected': (),
'type': 'multiSelect',
'value': ()}

Let's provide some values for this widget. We can do this by defining a source
providing ``ITerms``. This source uses descriminators wich will fit our setup.

Expand Down Expand Up @@ -132,6 +147,24 @@ If we select item "b", then it should be selected:
<option value="b">B</option>
</select>

The json data representing the oredered select widget:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'input',
'name': 'widget.name',
'notSelected': [{'content': 'A', 'id': 'widget-id-0', 'value': 'a'},
{'content': 'C', 'id': 'widget-id-2', 'value': 'c'}],
'options': [{'content': 'A', 'id': 'widget-id-0', 'value': 'a'},
{'content': 'B', 'id': 'widget-id-1', 'value': 'b'},
{'content': 'C', 'id': 'widget-id-2', 'value': 'c'}],
'required': False,
'selected': [{'content': 'B', 'id': 'widget-id-0', 'value': 'b'}],
'type': 'multiSelect',
'value': ['b']}

Let's now make sure that we can extract user entered data from a widget:

>>> widget.request = testing.TestRequest(form={'widget.name': ['c']})
Expand Down
5 changes: 5 additions & 0 deletions src/z3c/form/browser/radio.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ def update(self):
{'id':id, 'name':self.name, 'value':term.token,
'label':label, 'checked':checked})

def json_data(self):
data = super(RadioWidget, self).json_data()
data['options'] = self.items
data['type'] = 'radio'
return data

@zope.component.adapter(zope.schema.interfaces.IField, interfaces.IFormLayer)
@zope.interface.implementer(interfaces.IFieldWidget)
Expand Down
44 changes: 44 additions & 0 deletions src/z3c/form/browser/radio.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,28 @@ Now let's try if we get widget values:
</span>
<input name="widget.name-empty-marker" type="hidden" value="1" />

The radio json_data representation:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'input',
'name': 'widget.name',
'options': [{'checked': False,
'id': 'widget-id-0',
'label': 'yes',
'name': 'widget.name',
'value': 'true'},
{'checked': False,
'id': 'widget-id-1',
'label': 'no',
'name': 'widget.name',
'value': 'false'}],
'required': False,
'type': 'radio',
'value': ()}

If we set the value for the widget to ``yes``, we can se that the radio field
get rendered with a checked flag:

Expand All @@ -113,6 +135,28 @@ get rendered with a checked flag:
</span>
<input name="widget.name-empty-marker" type="hidden" value="1" />

The radio json_data representation:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'input',
'name': 'widget.name',
'options': [{'checked': True,
'id': 'widget-id-0',
'label': 'yes',
'name': 'widget.name',
'value': 'true'},
{'checked': False,
'id': 'widget-id-1',
'label': 'no',
'name': 'widget.name',
'value': 'false'}],
'required': False,
'type': 'radio',
'value': 'true'}

We can also render the input elements for each value separately:

>>> print(widget.renderForValue('true'))
Expand Down
6 changes: 6 additions & 0 deletions src/z3c/form/browser/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ def addItem(idx, term, prefix=''):
addItem(idx, term, prefix='missing-')
return items

def json_data(self):
data = super(SelectWidget, self).json_data()
data['options'] = self.items()
data['type'] = 'select'
return data


@zope.component.adapter(zope.schema.interfaces.IChoice, interfaces.IFormLayer)
@zope.interface.implementer(interfaces.IFieldWidget)
Expand Down
83 changes: 83 additions & 0 deletions src/z3c/form/browser/select.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,34 @@ Now let's try if we get widget values:
</select>
<input name="widget.name-empty-marker" type="hidden" value="1" />

Select json_data representation:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'input',
'name': 'widget.name',
'options': [{'content': 'No value',
'id': 'widget-id-novalue',
'selected': False,
'value': '--NOVALUE--'},
{'content': 'a',
'id': 'widget-id-0',
'selected': False,
'value': 'a'},
{'content': 'b',
'id': 'widget-id-1',
'selected': False,
'value': 'b'},
{'content': 'c',
'id': 'widget-id-2',
'selected': False,
'value': 'c'}],
'required': False,
'type': 'select',
'value': ()}

If we select item "b", then it should be selected:

>>> widget.value = ['b']
Expand All @@ -91,6 +119,34 @@ If we select item "b", then it should be selected:
</select>
<input name="widget.name-empty-marker" type="hidden" value="1" />

Select json_data representation:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'input',
'name': 'widget.name',
'options': [{'content': 'No value',
'id': 'widget-id-novalue',
'selected': False,
'value': '--NOVALUE--'},
{'content': 'a',
'id': 'widget-id-0',
'selected': False,
'value': 'a'},
{'content': 'b',
'id': 'widget-id-1',
'selected': True,
'value': 'b'},
{'content': 'c',
'id': 'widget-id-2',
'selected': False,
'value': 'c'}],
'required': False,
'type': 'select',
'value': ['b']}

Let's see what happens if we have values that are not in the vocabulary:

>>> widget.value = ['x', 'y']
Expand Down Expand Up @@ -169,6 +225,33 @@ by the adapter:
>>> widget.noValueMessage
u'- nothing -'

Select json_data representation:
>>> from pprint import pprint
>>> pprint(widget.json_data())
{'error': '',
'id': 'widget-id',
'label': '',
'mode': 'input',
'name': 'widget.name',
'options': [{'content': '- nothing -',
'id': 'widget-id-novalue',
'selected': True,
'value': '--NOVALUE--'},
{'content': 'a',
'id': 'widget-id-0',
'selected': False,
'value': 'a'},
{'content': 'b',
'id': 'widget-id-1',
'selected': False,
'value': 'b'},
{'content': 'c',
'id': 'widget-id-2',
'selected': False,
'value': 'c'}],
'required': False,
'type': 'select',
'value': []}

Explicit Selection Prompt
-------------------------
Expand Down
Loading

0 comments on commit df4c3d0

Please sign in to comment.