Example and tests
=================

Define a wizard with three steps
--------------------------------

To define a form that uses the wizard, we'll need to define steps.
These steps represent individual forms that are processed
sequentially.  Only when the last step is completed will the data be
submitted through a user-defined method.

  >>> from zope import schema
  >>> from z3c.form import field, form
  >>> from collective.z3cform.wizard import wizard
  >>> from plone.z3cform.fieldsets import group

  >>> class StepOne(wizard.Step):
  ...     prefix = 'one'
  ...     fields = field.Fields(
  ...         schema.Int(__name__='age', title=u"Age"))

By default, the steps will get/set values in the session.  If we want to
initialize these values or do something with them once the wizard is completed,
we need to implement the load and apply methods for our step.

  >>> from pprint import pprint
  >>> class StepTwo(wizard.Step):
  ...     prefix = 'two'
  ...     fields = field.Fields(
  ...         schema.TextLine(__name__='name', title=u"Name", required=True))
  ...         
  ...     def load(self, context):
  ...         data = self.getContent()
  ...         data['name'] = 'David'
  ...         
  ...     def apply(self, context):
  ...         data = self.getContent()
  ...         pprint('Name from step 2: %s' % data['name'])

We can also do group steps

  >>> class AddressGroup(group.Group):
  ...   fields = field.Fields(
  ...     schema.TextLine(__name__='address', title=u'Address', required=False),
  ...     schema.TextLine(__name__='city', title=u'City', required=False),
  ...     schema.TextLine(__name__='state', title=u'State', required=False))
  ...   label = u"Address Information"
  ...   prefix = 'address'

  >>> class StepThree(wizard.GroupStep):
  ...   prefix = 'three'
  ...   fields = field.Fields()
  ...   groups = [AddressGroup]


We can now define our minimal wizard:

  >>> class Wizard(wizard.Wizard):
  ...     label = u"My silly wizard"
  ...     steps = StepOne, StepTwo, StepThree

Render the form
---------------

Let's render the form for the first time now:

  >>> request = TestRequest()
  >>> wizard = Wizard(None, request)
  >>> print wizard()
  <...
  <div class="form" id="wizard-step-one">
    <form action="http://127.0.0.1" method="post"
          class="enableUnloadProtection"
          enctype="multipart/form-data">
        <p class="discreet"></p>
    <div class="row">
        <div class="field">
          <label for="one-widgets-age">
            <span>Age</span>
          </label>...
          <span class="fieldRequired"
                title="Required">
            (Required)
          </span>
          <div class="widget">
            <input id="one-widgets-age" name="one.widgets.age"
                   class="text-widget required int-field" value=""
                   type="text" />
          </div>
        </div>
    </div>
    <hr />
    <div class="wizard-buttons">
        <div class="action">
            <input id="form-buttons-continue"
                   name="form.buttons.continue"
                   class="submit-widget button-field" value="Continue"
                   type="submit" />
        </div>
    </div>
    </form>
  </div>


Submit with an error
--------------------

Remember that our first step requires the age.

  >>> request.form = {
  ...     'form.buttons.continue': u'Continue',
  ... }
  >>> wizard = Wizard(None, request)
  >>> print wizard()
  <...
  <div class="form" id="wizard-step-one">
  ...There were errors...
  ...Required input is missing...

Submit the first step successfully
----------------------------------

  >>> request.form['one.widgets.age'] = u'27'
  >>> wizard = Wizard(None, request)
  >>> print wizard()
  <...
  <div class="form" id="wizard-step-two">
    <form action="http://127.0.0.1" method="post"
          class="enableUnloadProtection"
          enctype="multipart/form-data">
        <p class="discreet"></p>
    <div class="row">
        <div class="field">
          <label for="two-widgets-name">
            <span>Name</span>
          </label>
          <span class="fieldRequired"
                title="Required">
            (Required)
          </span>
          <div class="widget">
            <input id="two-widgets-name" name="two.widgets.name"
                   class="text-widget required textline-field"
                   value="David" type="text" />
          </div>  
        </div>
    </div>
      <hr />
      <div class="wizard-buttons">
          <div class="action">
            <input id="form-buttons-continue" name="form.buttons.continue"
                   class="submit-widget button-field" value="Continue"
                   type="submit" />
          </div>
          <div class="action">
            <input id="form-buttons-back" name="form.buttons.back"
                   class="submit-widget button-field" value="Back"
                   type="submit" />
          </div>
      </div>
    </form>
  </div>

Submitting step two
-------------------

Step two works similarly:

  >>> request.form['two.widgets.name'] = u'David'
  >>> wizard = Wizard(None, request)
  >>> html = wizard()
  >>> 'three' in html, 'Address' in html, 'City' in html, 'State' in html, 'Finish' in html
  (True, True, True, True, True)


Step Three: Slaying the dragon
------------------------------

Now let's press the Finish button.  We expect this to print out the value
from step 2, thanks to the 'apply' method we implemented for that step.

Remembering that in our wizard, we implemented ``finish`` to print out
the data that it receives.  Here's the finishing move:

  >>> request.form['form.buttons.finish'] = u'Finish'
  >>> wizard = Wizard(None, request)
  >>> html = wizard()
  'Name from step 2: David'

  >>> print html
  <...
  <div class="form">
    <div class="portalMessage">Information submitted successfully.</div>
  </div>...


Example
-------

See the `collective.megaphone`_ package for an example of this library in use.

.. _`collective.megaphone`: http://plone.org/products/megaphone
