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.



_______________________________________________
List: Catalyst@lists.rawmode.org
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.rawmode.org/
Dev site: http://dev.catalyst.perl.org/

Reply via email to