<html><head><title>Mojolicious::Plugin::FormFields</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" >
</head>
<body class='pod'>
<!--
generated by Pod::Simple::HTML v3.28,
using Pod::Simple::PullParser v3.28,
under Perl v5.018001 at Sat Jun 14 02:51:03 2014 GMT.
If you want to change this HTML document, you probably shouldn't do that
by changing it directly. Instead, see about changing the calling options
to Pod::Simple::HTML, and/or subclassing Pod::Simple::HTML,
then reconverting this document from the Pod source.
When in doubt, email the author of Pod::Simple::HTML for advice.
See 'perldoc Pod::Simple::HTML' for more info.
-->
<!-- start doc -->
<a name='___top' class='dummyTopAnchor' ></a>
<h1><a class='u'
name="NAME"
>NAME</a></h1>
<p>Mojolicious::Plugin::FormFields - Lightweight form builder with validation and filtering</p>
<h1><a class='u'
name="SYNOPSIS"
>SYNOPSIS</a></h1>
<pre> $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->field('user.name')->is_required;
$self->field('user.password')->is_required->is_equal('user.confirm_password');
if($self->valid) {
$self->users->update($self->param('user'));
$self->redirect_to('/profile');
return;
}
}
# In your view
field('user.name')->text
field('user.name')->error unless field('user.name')->valid
field('user.password')->password
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->error('name') unless $user->valid('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')
# ...
}</pre>
<h1><a class='u'
name="DESCRIPTION"
>DESCRIPTION</a></h1>
<p><code>Mojolicious::Plugin::FormFields</code> allows you to bind objects and data structures to form fields. It also performs validation and filtering via <a href="http://search.cpan.org/perldoc?Validate%3A%3ATiny" class="podlinkpod"
>Validate::Tiny</a>.</p>
<h1><a class='u'
name="CREATING_FIELDS"
>CREATING FIELDS</a></h1>
<p>Fields can be bound to a hash, an array, something blessed, or any combination of the three. They are created by calling the <code><a href="#field" class="podlinkpod"
>"field"</a></code> helper with a path to the value you want to bind, and then calling the desired HTML input method</p>
<pre> field('user.name')->text</pre>
<p>Is the same as</p>
<pre> text_field 'user.name', $user->name, id => 'user-name'</pre>
<p>(though <code>Mojolicious::Plugin::FormFields</code> sets <code>type="text"</code>).</p>
<p>Field names/paths are given in the form <code>target.accessor1 [ .accessor2 [ .accessorN ] ]</code> where <code>target</code> is an object or data structure and <code>accessor</code> is a method, hash key, or array index. The target must be in the stash under the key <code>target</code> or provided as an argument to <code><a href="#field" class="podlinkpod"
>"field"</a></code>.</p>
<p>Some examples:</p>
<pre> field('users.0.name')->text</pre>
<p>Is the same as</p>
<pre> text_field 'users.0.name', $users->[0]->name, id => 'users-0-name'</pre>
<p>And</p>
<pre> field('item.orders.0.XAJ123.quantity')->text</pre>
<p>Is equivalent to</p>
<pre> text_field 'item.orders.0.XAJ123.quantity', $item->orders->[0]->{XAJ123}->quantity, id => 'item-orders-0-XAJ123-quantity'</pre>
<p>As you can see DOM IDs are always created.</p>
<p>Here the target key <code>book</code> does not exist in the stash so the target is supplied</p>
<pre> field('book.upc', $item)->text</pre>
<p>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.</p>
<p>Options can also be provided</p>
<pre> field('user.name')->text(class => 'input-text', 'data-name' => 'xxx')</pre>
<p>See <a href="#SUPPORTED_FIELDS" class="podlinkpod"
>"SUPPORTED FIELDS"</a> for the list of HTML input creation methods.</p>
<h2><a class='u'
name="STRUCTURED_REQUEST_PARAMETERS"
>STRUCTURED REQUEST PARAMETERS</a></h2>
<p>Structured request parameters for the bound object/data structure are available via <code>Mojolicious::Controller</code>'s <a href="http://search.cpan.org/perldoc?Mojolicious%3A%3AController%23param" class="podlinkpod"
>param method</a>. They can not be accessed via <code>Mojo::Message::Request</code>.</p>
<p>A request with the parameters <code>user.name=nameA&user.email=email&id=123</code> can be accessed in your action like</p>
<pre> my $user = $self->param('user');
$user->{name};
$user->{email};</pre>
<p>Other parameters can be accessed as usual</p>
<pre> $id = $self->param('id');</pre>
<p>The flattened parameter can also be used</p>
<pre> $name = $self->param('user.name');</pre>
<p>See <a href="http://search.cpan.org/perldoc?Mojolicious%3A%3APlugin%3A%3AParamExpand" class="podlinkpod"
>Mojolicious::Plugin::ParamExpand</a> for more info.</p>
<h2><a class='u'
name="SCOPING"
>SCOPING</a></h2>
<p>Fields can be scoped to a particular object/data structure via the <code><a href="#fields" class="podlinkpod"
>"fields"</a></code> helper</p>
<pre> my $user = fields('user');
$user->text('name');
$user->hidden('id');</pre>
<p>When using <code>fields</code> you must supply the field's name to the HTML input and validation methods, otherwise the calls are the same as they are with <code>field</code>.</p>
<h2><a class='u'
name="COLLECTIONS"
>COLLECTIONS</a></h2>
<p>You can also create fields scoped to elements in a collection</p>
<pre> my $addresses = field('user.addresses');
for my $addr (@$addresses) {
# field('user.addresses.N.id')->hidden
$addr->hidden('id');
# field('user.addresses.N.street')->text
$addr->text('street');
# field('user.addresses.N.city')->select([qw|OAK PHL LAX|])
$addr->select('city', [qw|OAK PHL LAX|]);
}</pre>
<p>Or, for fields that are already scoped</p>
<pre> my $user = fields('user')
$user->hidden('id');
my $addressess = $user->fields('addresses');
for my $addr (@$addresses) {
$addr->hidden('id')
# ...
}</pre>
<p>You can also access the underlying object and its position within a collection via the <code>object</code> and <code>index</code> methods.</p>
<pre> <% for my $addr (@$addresses) { %>
<div id="<%= dom_id($addr->object) %>">
<h3>Address #<%= $addr->index + 1 %></h3>
<%= $addr->hidden('id') %>
...
</div>
<% } %></pre>
<h1><a class='u'
name="VALIDATING_&_FILTERING"
>VALIDATING & FILTERING</a></h1>
<p>Validation rules are created by calling validation and/or filter methods on the field to be validated</p>
<pre> # In your controller
my $self = shift;
$self->field('user.name')->is_required;
$self->field('user.name')->filter('trim');</pre>
<p>These methods can be chained</p>
<pre> $self->field('user.name')->is_required->filter('trim');</pre>
<p>To perform validation on a field call its <code>valid</code> method</p>
<pre> $field = $self->field('user.name');
$field->is_required;
$field->valid;
$field->error;</pre>
<p>This will only validate and return the error for the <code>user.name</code> field. To validate all fields and retrieve all error messages call the controller's <code>valid</code> and <code>errors</code> methods</p>
<pre> $self->field('user.name')->is_required;
$self->field('user.age')->is_like(qr/^\d+$/);
$self->valid;
my $errors = $self->errors;
$errors->{'user.name'}
# ...</pre>
<p>Of course the <code>error</code>/<code>errors</code> and <code>valid</code> methods can be used in your view too</p>
<pre> <% unless(valid()) { %>
<p>Hey, fix the below errors</p>
<% } %>
<%= field('name')->text %>
<% unless(field('name')->valid) { %>
<span class="error"><%= field('name')->error %></span>
<% } %></pre>
<p>When creating validation rules for <a href="#fields" class="podlinkpod"
>"fields"</a> you must pass the field name as the first argument</p>
<pre> my $user = fields('user');
$user->is_required('password');
$user->is_equal(password => 'confirm_password');
$user->is_long_at_least(password => 8, 'Mais longo caipira');</pre>
<h2><a class='u'
name="AVAILABLE_RULES_&_FILTERS"
>AVAILABLE RULES & FILTERS</a></h2>
<p><code>Mojolicious::Plugin::FormFields</code> uses <code>Validate::Tiny</code>, see <a href="http://search.cpan.org/perldoc?Validate%3A%3ATiny#filter" class="podlinkpod"
>its docs</a> for a list.</p>
<h2><a class='u'
name="RENAMING_THE_VALIDATION_METHODS"
>RENAMING THE VALIDATION METHODS</a></h2>
<p>In the event that the <code>valid</code> and/or <code>errors</code> methods clash with exiting methods/helpers in your app you can rename them by specifying alternate names when loading the plugin</p>
<pre> $self->plugin('FormFields', methods => { valid => 'form_valid', errors => 'form_errors' });
# ...
$self->field('user.name')->is_required;
$self->form_valid;
$self->form_errors;</pre>
<p>Note that this <i>only</i> changes the methods <b>on the controller</b> and does not change the methods on the object returned by <code>field</code>.</p>
<h1><a class='u'
name="METHODS"
>METHODS</a></h1>
<h2><a class='u'
name="field"
>field</a></h2>
<pre> field($name)->text
field($name, $object)->text</pre>
<h3><a class='u'
name="Arguments"
>Arguments</a></h3>
<p><code>$name</code></p>
<p>The field's name, which can also be the path to its value in the stash. See <a href="#CREATING_FIELDS" class="podlinkpod"
>"CREATING FIELDS"</a>.</p>
<p><code>$object</code></p>
<p>Optional. The object used to retrieve the value specified by <code>$name</code>. 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 <code>$name</code>.</p>
<h3><a class='u'
name="Returns"
>Returns</a></h3>
<p>An object than can be used to create HTML form fields, see <a href="#SUPPORTED_FIELDS" class="podlinkpod"
>"SUPPORTED FIELDS"</a>.</p>
<h3><a class='u'
name="Errors"
>Errors</a></h3>
<p>An error will be raised if:</p>
<ul>
<li><code>$name</code> is not provided</li>
<li><code>$name</code> cannot be retrieved from <code>$object</code></li>
<li><code>$object</code> cannot be found in the stash and no default was given</li>
</ul>
<h3><a class='u'
name="Collections"
>Collections</a></h3>
<p>See <a href="#COLLECTIONS" class="podlinkpod"
>"COLLECTIONS"</a></p>
<h2><a class='u'
name="fields"
>fields</a></h2>
<pre> $f = fields($name)
$f->text('address')
$f = fields($name, $object)
$f->text('address')</pre>
<p>Create form fields scoped to a parameter.</p>
<p>For example</p>
<pre> % $f = fields('user')
%= $f->select('age', [10,20,30])
%= $f->textarea('bio')</pre>
<p>Is the same as</p>
<pre> %= field('user.age')->select([10,20,30])
%= field('user.bio')->textarea</pre>
<h3><a class='u'
name="Arguments"
>Arguments</a></h3>
<p>Same as <a href="#field" class="podlinkpod"
>"field"</a>.</p>
<h3><a class='u'
name="Returns"
>Returns</a></h3>
<p>An object than can be used to create HTML form fields scoped to the <code>$name</code> argument, see <a href="#SUPPORTED_FIELDS" class="podlinkpod"
>"SUPPORTED FIELDS"</a>.</p>
<h3><a class='u'
name="Errors"
>Errors</a></h3>
<p>Same as <a href="#field" class="podlinkpod"
>"field"</a>.</p>
<h3><a class='u'
name="Collections"
>Collections</a></h3>
<p>See <a href="#COLLECTIONS" class="podlinkpod"
>"COLLECTIONS"</a></p>
<h1><a class='u'
name="SUPPORTED_FIELDS"
>SUPPORTED FIELDS</a></h1>
<h2><a class='u'
name="checkbox"
>checkbox</a></h2>
<pre> field('user.admin')->checkbox(%options)
field('user.admin')->checkbox('yes', %options)</pre>
<p>Creates</p>
<pre> <input type="checkbox" name="user.admin" id="user-admin-1" value="1"/>
<input type="checkbox" name="user.admin" id="user-admin-yes" value="yes"/></pre>
<h2><a class='u'
name="file"
>file</a></h2>
<pre> field('user.avatar')->file(%options);</pre>
<p>Creates</p>
<pre> <input id="user-avatar" name="user.avatar" type="file" /></pre>
<h2><a class='u'
name="hidden"
>hidden</a></h2>
<pre> field('user.id')->hidden(%options)</pre>
<p>Creates</p>
<pre> <input id="user-id" name="user.id" type="hidden" value="123123" /></pre>
<h2><a class='u'
name="input"
>input</a></h2>
<pre> field('user.phone')->input($type, %options)</pre>
<p>For example</p>
<pre> field('user.phone')->input('tel', pattern => '\d{3}-\d{4}')</pre>
<p>Creates</p>
<pre> <input id="user-phone" name="user.phone" type="tel" pattern="\d{3}-\d{4}" /></pre>
<h2><a class='u'
name="label"
>label</a></h2>
<pre> field('user.name')->label
field('user.name')->label('Nombre', for => "tu_nombre_hyna")</pre>
<p>Creates</p>
<pre> <label for="user-name">Name</label>
<label for="tu_nombre_hyna">Nombre</label></pre>
<h2><a class='u'
name="password"
>password</a></h2>
<pre> field('user.password')->password(%options)</pre>
<p>Creates</p>
<pre> <input id="user-password" name="user.password" type="password" /></pre>
<h2><a class='u'
name="select"
>select</a></h2>
<pre> field('user.age')->select([10,20,30], %options)
field('user.age')->select([[Ten => 10], [Dub => 20], [Trenta => 30]], %options)</pre>
<p>Creates</p>
<pre> <select id="user-age" name="user.age">
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
</select>
<select id="user-age" name="user.age">
<option value="10">Ten</option>
<option value="20">Dub</option>
<option value="30">Trenta</option>
</select></pre>
<h2><a class='u'
name="radio"
>radio</a></h2>
<pre> field('user.age')->radio('older_than_21', %options)</pre>
<p>Creates</p>
<pre> <input id="user-age-older_than_21" name="user.age" type="radio" value="older_than_21" /></pre>
<h2><a class='u'
name="text"
>text</a></h2>
<pre> field('user.name')->text(%options)
field('user.name')->text(size => 10, maxlength => 32)</pre>
<p>Creates</p>
<pre> <input id="user-name" name="user.name" value="sshaw" />
<input id="user-name" name="user.name" value="sshaw" size="10" maxlength="32" /></pre>
<h2><a class='u'
name="textarea"
>textarea</a></h2>
<pre> field('user.bio')->textarea(%options)
field('user.bio')->textarea(size => '10x50')</pre>
<p>Creates</p>
<pre> <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></pre>
<h1><a class='u'
name="AUTHOR"
>AUTHOR</a></h1>
<p>Skye Shaw (sshaw [AT] gmail.com)</p>
<h1><a class='u'
name="SEE_ALSO"
>SEE ALSO</a></h1>
<p><a href="http://search.cpan.org/perldoc?Mojolicious%3A%3APlugin%3A%3ATagHelpers" class="podlinkpod"
>Mojolicious::Plugin::TagHelpers</a>, <a href="http://search.cpan.org/perldoc?Mojolicious%3A%3APlugin%3A%3AParamExpand" class="podlinkpod"
>Mojolicious::Plugin::ParamExpand</a>, <a href="http://search.cpan.org/perldoc?Validate%3A%3ATiny" class="podlinkpod"
>Validate::Tiny</a>, <a href="http://search.cpan.org/perldoc?Mojolicious%3A%3APlugin%3A%3ADomIdHelper" class="podlinkpod"
>Mojolicious::Plugin::DomIdHelper</a></p>
<h1><a class='u'
name="COPYRIGHT"
>COPYRIGHT</a></h1>
<p>Copyright (c) 2012-2014 Skye Shaw.</p>
<p>This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.</p>
<!-- end doc -->
</body></html>