Provided by: libbread-board-perl_0.32-1_all bug

NAME

       Bread::Board::Manual::Example::FormSensible - A Form::Sensible and Catalyst example.

VERSION

       version 0.32

SYNOPSIS

         __PACKAGE__->config(
             # ... your other Catalyst configs ...

             # first put our universal
             # FormBuilder container
             # inside the config
             FormBuilder => container 'FormBuilder' => [ 'Fields' ] => as {
                 service 'Form' => (
                     class => 'Form::Sensible',
                     block => sub {
                         my $s      = shift;
                         my $c      = $s->parent;
                         my $fields = $c->get_sub_container('Fields');
                         my $form   = Form::Sensible::Form->new( name => $s->param('name') );
                         foreach my $name ( $fields->get_service_list ) {
                             $form->add_field(
                                 $fields->get_service( $name )->get
                             );
                         }

                         if ( my $state = $s->param('state') ) {
                             $form->set_values( $state );
                         }

                         $form;
                     },
                     parameters => {
                         name  => { isa => 'Str'                    },
                         state => { isa => 'HashRef', optional => 1 },
                     }
                 );
             },

             # Then we can build a set of
             # Fields for the 'foo' form
             Fields => {
                 foo => container 'FooFields' => [ 'Model' ] => as {

                       service 'Username' => (
                           class => 'Form::Sensible::Field::Text',
                           block => sub {
                               Form::Sensible::Field::Text->new(
                                   name       => 'username',
                                   validation => { regex => qr/^[0-9a-z]*$/ }
                               );
                           }
                       );

                       service 'Password' => (
                           class => 'Form::Sensible::Field::Text',
                           block => sub {
                               Form::Sensible::Field::Text->new(
                                   name         => 'password',
                                   render_hints => {
                                       'HTML' => {
                                           field_type => 'password'
                                       }
                                   }
                               );
                           }
                       );

                       service 'Submit' => (
                           class => 'Form::Sensible::Field::Trigger',
                           block => sub {
                               Form::Sensible::Field::Trigger->new(
                                   name => 'submit'
                               );
                           }
                       );

                       service 'AccessLevel' => (
                           class => 'Form::Sensible::Field::Select',
                           block => sub {
                               my $s = shift;
                               my $select = Form::Sensible::Field::Select->new(
                                    name => 'access_level',
                               );
                               foreach my $access_level ( $s->param('schema')->resultset('AccessLevels')->all ) {
                                   $select->add_option(
                                       $access_level->id,
                                       $access_level->name
                                   );
                               }
                               $select;
                           },
                           dependencies => {
                               schema => depends_on('Model/schema') ,
                           },
                       );
                   }
             }
         );

         # later, in a
         # catalyst action ...
         sub process_foo : Local {
             my ($self, $c) = @_;
             my $Model = container 'Model' => as { service 'schema' => $c->model('DBIC') };
             my $Form  = $c->config->{FormBuilder}->create(
                 Fields => $c->config->{Fields}->{foo}->create(
                     Model => $Model
                 )
             );

             my $f = $Form->resolve(
                 service    => 'Form',
                 parameters => {
                     name  => 'foo',
                     state => $c->req->parameters
                 }
             );

             my $result = $f->validate;

             if ($result->is_valid) {
                 # ...
             }
             else {
                 # ...
             }
         }

DESCRIPTION

       This example came out of a discussion with Jay Kuri about how Bread::Board might be used
       in conjunction with his Form::Sensible module.

       My idea was to create a generic form builder which is parameterized by a Fields container.
       This could be used to store all kind of application wide behaviors. Since this in the
       context of Catalyst it made sense to me for this to be stuffed into the Catalyst config
       hash. I also decided to use service parameters in the Form service, this allows you to
       pass in a specific name and to optionally pass in a captured state to the
       Form::Sensible::Form instance that is being created.

       The next idea was that the Fields container parameter could be created for each specific
       form in the application. In the above example all the services are hardcoded, but this
       could be made more re-usable using the "include" keyword from Bread::Board itself, or some
       degree of subclassing of the Container objects.

       Jay also asked about passing in the Catalyst model into the fields so that he could
       populate something like a select pulldown menu. Again I used parameterized modules, in
       this case we parameterized the FooFields container with a Model container which had a
       schema service (which was a DBIx::Class schema object).

       From here we move into a Catalyst action to show how this might be used.  We start out by
       wrapping the Catalyst DBIC model with a simple container, and then proceed to build our
       $Form object. The $Form is a Bread::Board container born of 3 levels of parameterized
       containers, it is worth spending a little time pondering exactly what is happening there.

       So once we have the $Form container, all we need to do is create an instance of our
       Form::Sensible::Form, passing in the name and the captured state.

       This example could likely be expanded even further to show the use of the Form::Sensible
       rendering as well. Further creative use of parameterized containers and a couple utility
       methods in the Catalyst controllers could produce fairly robust and easy to use API for an
       application.

AUTHOR

       Stevan Little <stevan@iinteractive.com>

COPYRIGHT AND LICENSE

       This software is copyright (c) 2014 by Infinity Interactive.

       This is free software; you can redistribute it and/or modify it under the same terms as
       the Perl 5 programming language system itself.

perl v5.18.2                                2014-Bread::Board::Manual::Example::FormSensible(3pm)