[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