Widgets using Templates and Schema Properties
*********************************************

Unlike utilities more directly focused on processing Web forms,
Flatland does not include any concept of “widgets” that render a
field.  It is however easy enough to employ Flatland’s “properties”
and markup generation support to build our own widget system.  This
also gives us complete control over the rendering.

   from flatland import Form, String

   Input = String.with_properties(widget='input', type='text')
   Password = Input.with_properties(type='password')

   class SignInForm(Form):
       username = Input.using(label='Username')
       password = Password.using(label='Password')


Rendering Widgets with Genshi
=============================

Macros via Genshi’s "py:def" directive would be a good way to
implement the actual widgets.  For example:

   <html
       xmlns:form="http://ns.discorporate.us/flatland/genshi"
       xmlns:py="http://genshi.edgewall.org/"
       py:strip=""
     >

     <py:def
         function="widget(field)"
         py:with="macro = value_of(field.properties.widget + '_widget')"
         py:replace="macro(field)"
       />

     <fieldset py:def="input_widget(field)">
       <form:with
           auto-domid="on"
           auto-for="on"
         >

         <label
             form:bind="field"
             py:content="field.label"
           />

         <input
             form:bind="field"
             type="${field.properties.type}"
           />

       </form:with>
     </fieldset>
   </html>

Typically we would call the "widget" macro manually for each field we
want rendered, and in the desired order, but for demonstrative
purposes we stub out widgets for each field in arbitrary order:

   <html
       xmlns:py="http://genshi.edgewall.org/"
       xmlns:xi="http://www.w3.org/2001/XInclude"
     >
     <xi:include href="widgets.html"/>
     <body>
       <form>
         ${widget(form['username'])}
         ${widget(form['password'])}
       </form>
     </body>
   </html>


Rendering with Jinja
====================

If you’re not using Genshi you can still benefit from Flatland’s
schema-aware markup generating support.  With Jinja we might implement
the macros as something resembling this:

   {% set html = form_generator %}

   {% macro widget(field) %}
     {%- set macro = {'input': input}[field.properties.widget] -%}
     {{- macro(field) -}}
   {% endmacro %}

   {% macro input(field) %}
     {%- do html.begin(auto_domid=true, auto_for=true) %}
   <fieldset>
     {{ html.label(field, contents=field.label) }}
     {{ html.input(field, type=field.properties.type) }}
   </fieldset>
     {%- do html.end() %}
   {% endmacro %}

Then we can simply import the "widget" macro to form templates:

   {% from 'widgets.html' import widget -%}
   <html>
     <body>
       <form>
         {{- widget(form['username']) }}
         {{- widget(form['password']) }}
       </form>
     </body>
   </html>

Make sure to add a markup generator to the globals of your Jinja
environment:

   from flatland.out.markup import Generator
   jinja_env.globals['form_generator'] = Generator('html')
