[Catalyst] best practices for handling forms?

Octavian Rasnita octavian.rasnita at ssifbroker.ro
Tue Sep 21 06:18:37 GMT 2010


Hi,

A clean example that uses HTML::FormFu is:

package MyApp::Controller::Foo;

use Moose;
extends 'Catalyst::Controller::HTML::FormFu';
# or just  use parent 'Catalyst::Controller::HTML::FormFu' if you don't use 
Moose

sub edit : Local FormConfig {
  my ($self, $c, $id) = @_;

  my $form = $c->stash->{form};
  my $foo = $c->model("DB::Foo")->find($id);

  if ($form->submitted_and_valid) {
    $form->model->update($foo);
    $c->flash(notice => "Foo was updated successfully.");
    $c->res->redirect($c->uri_for_action('/foo/index'));
  }
  else {
    $form->model->default_values($foo);
  }
}


sub edit : Local FormConfig {

You can use Path or the chaining dispatch type or something else, not only 
"Local".
If you use the attribute FormConfig, it will search for the form placed by 
default in
root/forms/foo/edit.conf

If you want to use another specified form, you can use something like:

sub edit : Local FormConfig('path/to/another/form') {


  my $form = $c->stash->{form};

If you use the FormConfig attribute, it will place the form in the stash 
automaticly so you just need to get it from there.


  my $foo = $c->model("DB::Foo")->find($id);

This uses DBIx::Class result class DB::Foo for getting the $foo record.


if ($form->submitted_and_valid) {

This will be true only if the form past all the validation and constraints.

$form->model->update($foo);

This will update the $foo record in the database. In order to work this way, 
you need to have defined the database schema in myapp.conf like:

'Controller::HTML::FormFu' => {
  model_stash => {
    schema => 'DB',
  },
},

And in the edit.conf form configuration file (defined below using 
Config::General) you will need to have defined the resultset like:

<model_config>
resultset Foo
</model_config>


$c->res->redirect($c->uri_for_action('/foo/index'));

$c->uri_for_action is prefered because /foo/index is not a URI but an 
internal path to the index action from the Foo controller and this code 
doesn't need to be changed even if the public URI to that action changes.

$form->model->default_values($foo);

This fills the form with the values from $foo record when the form is 
displayed.

HTH.

--Octavian

----- Original Message ----- 
From: "E R" <pc88mxer at gmail.com>
To: "The elegant MVC web framework" <catalyst at lists.scsys.co.uk>
Sent: Tuesday, September 21, 2010 12:48 AM
Subject: [Catalyst] best practices for handling forms?


> 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 = Book.find(params[:id])
>      @subjects = Subject.find(:all)
>   end
>   def update
>      @book = Book.find(params[:id])
>      if @book.update_attributes(params[:book])
>         flash[:notice] = 'Book successfully updated.'
>         redirect_to :action => 'show', :id => @book
>      else
>         @subjects = Subject.find(:all)
>         render :action => '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) = @_;
>  ... 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) = @_;
>  ...process form...
>  if (form is valid) {
>    ...perform updates...
>    $c->flash->{notice} = 'Book successfully updated.';
>    $c->res->redirect('show', $id);
>  } else {
>    ... set up $c->stash for 'edit' template ...
>    $c->stash->{template} = '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/ 




More information about the Catalyst mailing list