Querying fields before merge

Sometimes it can be really nice (read: improve the user experience) to be able to query some fields without merging the value from the form back into an object. An example is when a user changes a input select field in a form which has an attached value. In an app we have, a user has a select list of product numbers. We make the app update the product's name on the page when the product changes.

Note that we are treading on thin ice here: if the user has not entered a valid value for the field, when get_value tries to convert it to the appropriate type, it will raise an exception that will need to be dealt with. It is (generally) safe to reference values from a TextField or a SelectField though.

   1 class ProductFieldsetForm(FieldsetForm):
   2 
   3     products_menu = product_factory.all_products_menu()
   4 
   5     def __init__(self, product):
   6         self.product_id = product.product_id
   7         elements = (
   8             Fieldset((
   9                 SelectField('Product code', self.products_menu, 'product_id',
  10                                  html_attrs={'onchange': 'javascript:product_form.submit()'}),
  11                 StaticField('Product', product.name),
  12             )),
  13         )
  14         FieldsetForm.__init__(self, 'Product selection', elements)
  15         
  16         self.load(product)  
  17 
  18     def update(self):
  19         product_code_field = self.get_field('Product code')
  20         if self.product_id != product_code_field.get_value():
  21             self.product_id = product_code_field.get_value()
  22             product = product_factory.product_with_product_id(self.product_id)
  23             product_field = self.get_field('Product')
  24             product_field.set_value(product.name)

The interesting part here is where we query the form for a specific field using its get_field method.

We use the little bit of Javascript to make a change to the select list force an update to the page. That means having to name the form when we render the page:

In the app itself, we use:

   1 def page_enter(ctx):
   2     if not ctx.has_value('product_form'):
   3         ctx.locals.product_form = ProductForm(ctx.locals.product)
   4         ctx.add_session_vars('product_form')
   5 
   6 def page_process(ctx):
   7     ctx.locals.product_form.update()      # update product name if product changed
   8     if ctx.request('save'):
   9         [...]

None: Querying_fields_before_merge (last edited 2011-02-15 06:05:17 by localhost)