[Catalyst] best practices for handling forms?

Hernan Lopes hernanlopes at gmail.com
Mon Sep 20 23:09:56 GMT 2010


perl Catalyst Forms with Formhandler and Thickbox:

You know you dont always need a template.tt2 file... this is useful with
ajax (especially with thickbox) so you can pass a scalar as template, so you
end up with:
 $c->stash( template =3D> $form->render, current_view =3D> 'Ajax', );
1. You could create an Ajax view.
2. Or you can set body content directly.
This way you skip creating TT files for forms and render them directly into
the $c->res->body or $c->stash( template =3D> \'foo baz')
If you use something like thickbox, you can render any $form directly into a
modal.
Its very handy!

For example:


__PACKAGE__->config(
    action =3D> {
        edit =3D> { Chained =3D> 'base', Args =3D> 1, },
    },
);

sub base : Chained('/') PathPart('foobar') CaptureArgs(0) {}

sub edit :Action {
  my ( $self, $c, $foobar_id ) =3D @_;
  my $form =3D HTML::FormHandler->new(
    schema =3D> 'DBSchema::Foo',
    params =3D> $c->req->params,
    field_list =3D> $self->form_fields($c),
      );
    if( $c->req->method eq 'POST' && $form->process() ) {
      ...
      } else {
  #OPTION 1 (create an Ajax View and create a wrapper for it. Then render
the form into stash template var):
        $c->stash(
          template =3D> \$form->render,
          current_view =3D> 'Ajax',
          );
  #OPTION 2 (set your content type and charset and render the form into the
body, needs no view/TT files):
        $c->res->content_type('text/html charset=3Dutf-8');
        $c->res->body($form->render);
        }
  }




sub form_fields {
    return [
        field_one =3D> {
        type =3D> 'Text',
        label =3D> '...',
        css_class =3D> '...',
        maxlength =3D> 160,
        required =3D> 1,
        required_message =3D> 'Required Text',
        },
        submit =3D> {
          type =3D> 'Submit',
          value =3D> 'Save',
          css_class =3D> '...',
         },
    ];
}



and DRY on edit & update unless necessary...
1. If there is an argument its "update?"
2. Else, when it has no args then its "edit/new" ?

use your foregin_key_id and $form('foregin_key_id')->value =3D '...' to set=
 it
, then formhandler will know whether to update or create a new entry.

Take care,
hernan





On Mon, Sep 20, 2010 at 6:48 PM, E R <pc88mxer at gmail.com> wrote:

> Hi,
>
> I am curious what everyone thinks as being the best practices for
> handling forms in Catalyst. Are there any Catalyst applications you
> have run across which are good examples of how to use Catalyst's
> features to handle forms?
>
> To illustrate what I am getting at, below is typical Rails (v2)
> controller code which implements updating the attributes of an object:
>
>   def edit
>      @book =3D Book.find(params[:id])
>      @subjects =3D Subject.find(:all)
>   end
>   def update
>      @book =3D Book.find(params[:id])
>      if @book.update_attributes(params[:book])
>         flash[:notice] =3D 'Book successfully updated.'
>         redirect_to :action =3D> 'show', :id =3D> @book
>      else
>         @subjects =3D Subject.find(:all)
>         render :action =3D> 'edit'
>      end
>   end
>
> In Catalyst, this would be appear something like (and please correct
> me if I have made any errors here):
>
> sub edit  :Args(1) {
>  my ($self, $c, $id) =3D @_;
>  ... set up $c->stash for template 'edit' ...
>  # no need to set $c->stash->{template} - will be set from the current
> action
> }
>
> sub update :Args(1) {
>  my ($self, $c, $id) =3D @_;
>  ...process form...
>  if (form is valid) {
>    ...perform updates...
>    $c->flash->{notice} =3D 'Book successfully updated.';
>    $c->res->redirect('show', $id);
>  } else {
>    ... set up $c->stash for 'edit' template ...
>    $c->stash->{template} =3D 'edit';
>  }
> }
>
> Any comments on this architecture? Is there a better way? My main problems
> are:
>
> 1. The code ... set up $c->stash for 'edit' template ... is duplicated
> in both edit and update (which is also true for the Rails code).
>
> 2. Having the template name defaulted from the current action is nice,
> but that means we have to explicitly set it in the update method. Is
> it better to always explicitly set the template name in a controller
> method? Then update could perform a $c->detach('edit', $id) or would
> you use $c->go('edit', $id)?
>
> Thanks,
> ER
>
> _______________________________________________
> List: Catalyst at lists.scsys.co.uk
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive:
> http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
> Dev site: http://dev.catalyst.perl.org/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20100920/1cfc9=
675/attachment.htm


More information about the Catalyst mailing list