[Catalyst] Trying to glue FormBuilder with Catalyst..

Dami Laurent (PJ) laurent.dami at justice.ge.ch
Thu Oct 13 14:54:17 CEST 2005


Hi everybody,

The following question was posted to the Catalyst list. I'm replying
both to the Catalyst and FBuilder lists, since it's really a
cross-domain question.


> Message: 3
> Date: Wed, 12 Oct 2005 15:27:58 +0200
> From: Bernard FRIT <bernard.frit at gmail.com>
> Subject: [Catalyst] Trying to glue FormBuilder with Catalyst..
> To: The elegant MVC web framework <catalyst at lists.rawmode.org>
> Message-ID: <3390cd220510120627q4a65918ej at mail.gmail.com>
> Content-Type: text/plain; charset=ISO-8859-1
> 
> Had anyone tried to make CGI::FormBuilder work within Catalyst ?
> 
> As formbuilder has his proper TT2 engine all I could have almost
> working (kinda dirty hack) is :
> 
> use CGI::FormBuilder;
> 
> my $test_form = CGI::FormBuilder->new(
>                 source => 
> '/home/livrepnl/www/Librairie/forms/test_form.conf',
>                 messages => 
> '/home/livrepnl/www/Librairie/forms/messages.fr');
> 
> [SNIP code]
> 
> sub edit_form : Local {
>     my ($self, $c) = @_;
> 
>     my $html = $test_form->render(template => {
>                      variable => 'form',
>                      type => 'TT2',
>                      template => 'test_form.xhtml',
>                      engine   => {
>                        INCLUDE_PATH => 
> '/home/livrepnl/www/Librairie/root',
>                      },
>                      });
> 
>     $c->res->output($html) ;
> }
> 
> (Need somme regexp against $html to remove extra Content-type and it
> works only within buildin catalyst server)
> 
> --
> Bernard FRIT
> 


I use both Catalyst and CGI::FormBuilder, but I had to twist a little
bit the FormBuilder philosophy. On the one hand, the $form->render()
expects to do most of the work (producing the entire page, possibly with
HTTP headers). On the other hand, the common pattern within Catalyst is
to set $c->stash->{template} within the handling method, and then wait
for the end of the request cycle (the end() method) to really send the
headers, call the appropriate template, etc. So the two philosophies
collide.

To solve this, I never call the $form->render() method directly.
Instead, I wrote a generic template called "form.tt" that mimics the
render() method : it iterates over the fields and produces a HTML table
with labels, input fields, comments, etc (source code below). Then, from
my Catalyst controllers, I just do something like 

  $c->stash->{form} = $myCgiFormBuilderObject;
  $c->stash->{template} = "form.tt"

and then, when MyApp::V::TT gets control, it prints the proper HTML
form. If the HTML output needs other stuff than just a form, it's no
problem : 

  $c->stash->{form} = $myCgiFormBuilderObject;
  $c->stash->{template} = "myVerySpecificPage.tt"

and of course "myVerySpecificPage.tt" contains somewhere a call to 

  [% PROCESS form.tt %]


Hope this helps. Below you will find the source code of "form.tt". 

Best regards, Laurent Dami

========================================================================
============
[% # form.tt -- reverse engineering of the CGI::FormBuilder::render
method %]

[% form.start;
   form.statetags;
   form.keepextras; %]

<small><em>Les elements en <b>gras</b> sont obligatoires</em></small>

<table>
  [% FOREACH field IN form.fields;  %]

  <tr valign="top">
    <td>
      [%- field.required ? "<b>$field.label</b>" : field.label -%]
    </td>
    <td>
      [% IF field.invalid %]
      Donnee manquante ou incorrecte, veuillez ressayer SVP.<br/>
      [% END # IF %]
      [% field.tag %]
      [% PROCESS libtt/calendarButton.tt IF isDate %]
      [% "<em>" _ field.comment _ "</em>" IF field.comment %]
     </td>
  </tr>
  [% END # FOREACH %]
  <tr>
    <td colspan="2" align="center">
      [% form.submit %] [% form.reset %]
    </td>
  </tr>
</table>

[% form.end %]




More information about the Catalyst mailing list