[Catalyst] Forms generation

Michael Reece mreece at vinq.com
Thu Jun 14 19:33:17 GMT 2007


On Jun 14, 2007, at 9:20 AM, Bill Moseley wrote:

> On Thu, Jun 14, 2007 at 11:34:52AM +0200, Leo Cacciari wrote:
>>    As I see it, the controller should tell the view 'I want the user
>> entering the following data, each one with its data-type, and obeying
>> the following constraints".
>
> I take that a step further, and say that the controller should say
> only "I want the user to update their profile"  and the controller
> shouldn't have to worry what fields and field types the "profile" is
> made up of.

i've implemented something similar to RoR-style form helpers, where  
the controller stashes the $user, and the view (mason here) does:

   <&| /form, for => $user, action => $c->uri_to('update_profile',  
$user->id) &>
     <& /text, name => 'username', label => 'Email address' &>
     <& /text, name => 'full_name' &>
     <& /checkbox_group, name => 'opt_in', choices => [ [ 0 =>  
'No'] , [ 1 => 'Yes' ] ] &>
     <&| /form:buttons &>
       <& /submit &>
       <& /cancel &>
     </&>
   </&>

and the mason components take care of populating input values (from  
object or previous request params), displaying inline errors  
(generated from Date::FV) on failed submission, all layout and field  
labeling requirements.

the end result is something like

   my $results = $self->check_form( Model::User->dfv_args_for_form 
('update_profile') );
   if ($results->has_missing || $results->has_invalid) {
     return $self->form_error( $results->msgs );
   } else {
     $user->update_from_hash($results->valid);
   }

i've been looking at Form::Processor and similar, but the tricky bit  
for me is that i want the view to be both responsible for generating  
the HTML and deciding which fields belong on which form, without an  
intermediate form object that has to inform both the view and  
controller.

the problem becomes giving the view a way to communicate the allowed  
fields back to the controller without trusting the client.

i've been experimenting with having my form component store the  
details in the session as its being rendered.

   <&| /form, for => $user, form_id => 'update_profile', ... &>
     <& /text, name => 'username', ... &>   <!-- pushes to @{ $c- 
 >session->{form_fields}->{update_profile} } -->
     ...

   my $fields = delete $c->session->{form_fields}->{update_profile};
   my $results = $self->check_form( Model::User->dfv_args_for_fields(@ 
$fields) );

i'm still teasing out the right API for this, but i do like how it  
gives authority to the view without also giving it to the client.





More information about the Catalyst mailing list