===========================
zeam.form.ztk radio widget
===========================

Simple case
===========

First we need a choice::

  >>> from zope import interface, schema
  >>> from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
  >>> from zope.interface.verify import verifyObject

  >>> def display_vocabulary(values):
  ...     for value in values:
  ...         print "%r %r %r" % (value.value, value.token, value.title)

  >>> letter_vocabulary = SimpleVocabulary([
  ...     SimpleTerm(value='A', token='a1', title='Letter A'),
  ...     SimpleTerm(value='B', token='b1', title='Letter B'),
  ...     SimpleTerm(value='C', token='c1', title='Letter C')])

  >>> class IFirstChoice(interface.Interface):
  ...     choice = schema.Choice(
  ...         title=u"My favorite letter",
  ...         source=letter_vocabulary)


And we will need a content and a request to test:

  >>> from zope.publisher.browser import TestRequest
  >>> request = TestRequest()

  >>> class FirstContent(object):
  ...    interface.implements(IFirstChoice)
  ...    choice = None
  >>> content = FirstContent()
  >>> content.choice = 'B'


Field
-----

So now you can create a field, and get a choice field::

  >>> from zeam.form.base import Fields
  >>> from zeam.form.base import interfaces

  >>> letter_fields = Fields(IFirstChoice)
  >>> letter_field = letter_fields['choice']
  >>> letter_field
  <ChoiceField My favorite letter>

  >>> letter_field.source is letter_vocabulary
  True

  >>> letter_field.validate('A', None)
  >>> letter_field.validate('foo', None)
   u'The selected value is not among the possible choices.'

  >>> verifyObject(interfaces.IField, letter_field)
  True

If we want to use a radio widget instead of the default selection widget
we have to change the default mode for our field to radio::
You can do this easily in the update method of your form.

  >>> letter_field.mode
  <Marker DEFAULT>

  >>> letter_field.mode = 'radio'


Widget
------

You have an associated widget::

  >>> from zeam.form.ztk import Widgets, FormData

  >>> firstForm = FormData(content, request)
  >>> firstForm.ignoreContent = False

  >>> firstWidgets = Widgets(
  ...     letter_fields,
  ...     form=firstForm,
  ...     request=request)

  >>> firstWidgets.update()

  >>> firstWidget = firstWidgets['form.field.choice']
  >>> firstWidget
  <RadioFieldWidget My favorite letter>

  >>> firstWidget.inputValue()
  'b1'

  >>> print firstWidget.render()
  <input type="radio" id="form-field-choice-0" name="form.field.choice" value="a1" class="field field-choice field-required" />
    <label for="form-field-choice-0">Letter A</label>
    <br />
  <input type="radio" id="form-field-choice-1" name="form.field.choice" value="b1" checked="checked" class="field field-choice field-required" />
    <label for="form-field-choice-1">Letter B</label>
    <br />
  <input type="radio" id="form-field-choice-2" name="form.field.choice" value="c1" class="field field-choice field-required" />
    <label for="form-field-choice-2">Letter C</label>
    <br />


Extractor
---------

We need a custom extractor as the token value used in the form can be
different than the real value::

  >>> from zope import component
  >>> from zeam.form.base import interfaces

  >>> firstExtractor = component.getMultiAdapter(
  ...      (letter_field, firstForm, request), interfaces.IWidgetExtractor)

  >>> firstExtractor
  <zeam.form.ztk.widgets.choice.ChoiceWidgetExtractor object at ...>
  >>> firstExtractor.extract()
  (<Marker NO_VALUE>, None)

Let's now do it with a value::

  >>> letter_request = TestRequest(
  ...         form={firstWidget.identifier: u'a1', })

  >>> letter_extractor = component.getMultiAdapter(
  ...      (letter_field, firstForm, letter_request), interfaces.IWidgetExtractor)

  >>> letter_extractor.extract()
  ('A', None)


Context binded source
=====================

Let's define a source which need the context to produce its values,
and an interface for it::

  >>> from grokcore import component
  >>> from zope.schema.interfaces import IContextSourceBinder

  >>> @component.provider(IContextSourceBinder)
  ... def context_vocabulary(context):
  ...     return letter_vocabulary

  >>> class IContextChoice(interface.Interface):
  ...     choice = schema.Choice(
  ...         title=u"My Choice",
  ...         source=context_vocabulary)

  >>> class ContextContent(object):
  ...    interface.implements(IContextChoice)
  ...    choice = None

  >>> content = ContextContent()
  >>> content.choice = 'C'

  >>> from zeam.form.ztk import FormData

  >>> context_form = FormData(content, request)
  >>> context_form.ignoreContent = False


Field
-----

So now you can create a field, and get a choice field::

  >>> from zeam.form.ztk import Fields

  >>> context_fields = Fields(IContextChoice)
  >>> context_field = context_fields['choice']
  >>> context_field
  <ChoiceField My Choice>
  >>> context_field.source is None
  True
  >>> context_field.vocabularyFactory is context_vocabulary
  True

  >>> choices = context_field.getChoices(context_form)
  >>> choices
  <zope.schema.vocabulary.SimpleVocabulary object at ...>
  >>> display_vocabulary(choices)
  'A' 'a1' 'Letter A'
  'B' 'b1' 'Letter B'
  'C' 'c1' 'Letter C'

  >>> context_field.validate('A', context_form)
  >>> context_field.validate(42, context_form)
  u'The selected value is not among the possible choices.'


Widget
------

You have an associated widget::

  >>> from zeam.form.ztk import Widgets

  >>> context_widgets = Widgets(
  ...     context_fields,
  ...     form=context_form,
  ...     request=request)

  >>> context_widgets.update()

  >>> context_widget = context_widgets['form.field.choice']
  >>> context_widget
  <ChoiceFieldWidget My Choice>

  >>> context_widget.inputValue()
  'c1'

  >>> print context_widget.render()
  <select id="form-field-choice" name="form.field.choice" class="field field-choice field-required" required="required">
    <option value="a1">Letter A</option>
    <option value="b1">Letter B</option>
    <option value="c1" selected="selected">Letter C</option>
  </select>
