Mojolicious::Plugin::FormFields - Use objects and data structures in your forms
$self->plugin('FormFields') # In your controller sub edit { my $self = shift; my $user = $self->users->find($self->param('id')); $self->stash(user => $user); } sub update { my $self = shift; $self->users->update($self->param('user')); } # In your view %= field('user.name')->text %= field('user.age')->select([10,20,30]) %= field('user.password')->password %= field('user.taste')->radio('me_gusta') %= field('user.taste')->radio('estoy_harto_de') %= field('user.orders.0.id')->hidden # Fields for a collection % my $kinfolk = field('user.kinfolk'); % for my $person (@$kinfolk) { %= $person->hidden('id') %= $person->text('name') % } # Or, scope it to the 'user' param % my $user = fields('user'); %= $user->hidden('id') %= $user->text('name') %= $user->label('admin') %= $user->checkbox('admin') %= $user->password('password') %= $user->select('age', [ [ X => 10], [Dub => 20] ]) %= $user->file('avatar') %= $user->textarea('bio', size => '10x50') % my $kinfolk = $user->fields('kinfolk'); % for my $person (@$kinfolk) { %= $person->text('name') # ... % }
Mojolicious::Plugin::FormFields binds objects and data structures to form fields. It does not perform validation.
Fields can be bound to a hash, an array, something blessed, or any combination of the three. They are created by calling the "field" helper with a path to the value you want to bind, and then calling the desired HTML input method
"field"
field('user.name')->text
Is the same as
text_field 'user.name', $user->name, id => 'user-name'
(though Mojolicious::Plugin::FormFields sets type="text").
Mojolicious::Plugin::FormFields
type="text"
Field names/paths are given in the form target.accessor1 [ .accessor2 [ .accessorN ] ] where target is an object or data structure and accessor is a method, hash key, or array index. The target must be in the stash under the key target or provided to "field".
target.accessor1 [ .accessor2 [ .accessorN ] ]
target
accessor
Some examples:
field('users.0.name')->text
text_field 'users.0.name', $users->[0]->name, id => 'users-0-name'
And
field('item.orders.0.XAJ123.quantity')->text
Is equivalent to
text_field 'item.orders.0.XAJ123.quantity', $item->orders->[0]->{XAJ123}->quantity, id => 'item-orders-0-XAJ123-quantity'
As you can see DOM IDs are always created.
Here the target key book does not exist in the stash so the target is supplied
book
field('book.upc', $item)->text
If a value for the flattened representation exists (e.g., from a form submission) it will be used instead of the value pointed at by the field name (desired behavior?). This is the same as Mojolicious' Tag Helpers.
Options can also be provided
field('user.name')->text(class => 'input-text', 'data-name' => 'xxx')
See "SUPPORTED FIELDS" for the list of HTML input creation methods.
Structured request parameters for the bound object/data structure are available via Mojolicious::Controller's param method. Nested parameters can not be accessed via Mojo::Message::Request.
Mojolicious::Controller
Mojo::Message::Request
A request with the parameters user.name=nameA&user.email=email&id=123 can be accessed in your action like
user.name=nameA&user.email=email&id=123
my $user = $self->param('user'); $user->{name}; $user->{email};
Other parameters can be accessed as usual
$id = $self->param('id');
The flattened parameter can also be used
$name = $self->param('user.name');
See Mojolicious::Plugin::ParamExpand for more info.
Fields can be scoped to a particular object/structure via the "fields" helper
"fields"
my $user = fields('user'); $user->text('name'); $user->hidden('id');
When using fields you must supply the field's name to the HTML input method, otherwise the calls are the same as with field.
fields
field
You can also create fields scoped to elements in a collection
my $addressees = field('user.addressees'); for my $addr (@$addressees) { # field('user.addressees.N.id')->hidden $addr->hidden('id'); # field('user.addressees.N.street')->text $addr->text('street'); # field('user.addressees.N.city')->select([qw|OAK PHL LAX|]) $addr->select('city', [qw|OAK PHL LAX|]); }
Or, for fields that are already scoped
my $user = fields('user') $user->hidden('id'); for my $addr ($user->fields('addressees')) { $addr->hidden('id') # ... }
field($name)->text field($name, $object)->text
$name
The field's name, which can also be the path to its value in the stash. See "CREATING FIELDS".
$object
Optional. The object used to retrieve the value specified by $name. Must be a reference to a hash, an array, or something blessed. If not given the value will be retrieved from the stash or, for previously submitted forms, the request parameter $name.
An object than can be used to create HTML form fields, see "SUPPORTED FIELDS".
An error will be raised if:
$name is not provided
$name cannot be retrieved from $object
$object cannot be found in the stash and no default was given
See "COLLECTIONS"
$f = fields($name) $f->text('address') $f = fields($name, $object) $f->text('address')
Create form fields scoped to a parameter.
For example
% $f = fields('user') %= $f->select('age', [10,20,30]) %= $f->textarea('bio')
%= field('user.age')->select([10,20,30]) %= field('user.bio')->textarea
Same as "field".
An object than can be used to create HTML form fields scoped to the $name argument, see "SUPPORTED FIELDS".
field('user.admin')->checkbox(%options) field('user.admin')->checkbox('yes', %options)
Creates
<input type="checkbox" name="user.admin" id="user-admin-1" value="1"/> <input type="checkbox" name="user.admin" id="user-admin-yes" value="yes"/>
field('user.avatar')->file(%options);
<input id="user-avatar" name="user.avatar" type="file" />
field('user.id')->hidden(%options)
<input id="user-id" name="user.id" type="hidden" value="123123" />
field('user.phone')->input($type, %options)
field('user.phone')->input('tel', pattern => '\d{3}-\d{4}')
<input id="user-phone" name="user.phone" type="tel" pattern="\d{3}-\d{4}" />
field('user.name')->label field('user.name')->label('Nombre', for => "tu_nombre_hyna")
<label for="user-name">Name</label> <label for="tu_nombre_hyna">Nombre</label>
field('user.password')->password(%options)
<input id="user-password" name="user.password" type="password" />
field('user.age')->select([10,20,30], %options) field('user.age')->select([[Ten => 10], [Dub => 20], [Trenta => 30]], %options)
<select id="user-age" name="user.age"> <option value="10">10</option> <option value="20">20</option> <option value="30" selected="selected">30</option> </select> <select id="user-age" name="user.age"> <option value="10">Ten</option> <option value="20">Dub</option> <option value="30" selected="selected">Trenta</option> </select>
field('user.age')->radio('older_than_21', %options)
<input id="user-age-older_than_21" name="user.age" type="radio" value="older_than_21" />
field('user.name')->text(%options) field('user.name')->text(size => 10, maxlength => 32)
<input id="user-name" name="user.name" value="sshaw" /> <input id="user-name" name="user.name" value="sshaw" size="10" maxlength="32" />
field('user.bio')->textarea(%options) field('user.bio')->textarea(size => '10x50')
<textarea id="user-bio" name="user.bio">Proprietary and confidential</textarea> <textarea cols="50" id="user-bio" name="user.bio" rows="10">Proprietary and confidential</textarea>
Mojolicious::Plugin::TagHelpers, Mojolicious::Plugin::ParamExpand, MojoX::Validator
To install Mojolicious::Plugin::FormFields, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Mojolicious::Plugin::FormFields
CPAN shell
perl -MCPAN -e shell install Mojolicious::Plugin::FormFields
For more information on module installation, please visit the detailed CPAN module installation guide.