<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-&#62;plugin(&#39;FormFields&#39;);

  # In your controller
  sub edit
  {
      my $self = shift;
      my $user = $self-&#62;users-&#62;find($self-&#62;param(&#39;id&#39;));
      $self-&#62;stash(user =&#62; $user);
  }

  sub update
  {
      my $self = shift;
      $self-&#62;field(&#39;user.name&#39;)-&#62;is_required;
      $self-&#62;field(&#39;user.password&#39;)-&#62;is_required-&#62;is_equal(&#39;user.confirm_password&#39;);

      if($self-&#62;valid) {
          $self-&#62;users-&#62;update($self-&#62;param(&#39;user&#39;));
          $self-&#62;redirect_to(&#39;/profile&#39;);
          return;
      }
  }

  # In your view
  field(&#39;user.name&#39;)-&#62;text
  field(&#39;user.name&#39;)-&#62;error unless field(&#39;user.name&#39;)-&#62;valid

  field(&#39;user.password&#39;)-&#62;password
  field(&#39;user.age&#39;)-&#62;select([10,20,30])
  field(&#39;user.password&#39;)-&#62;password
  field(&#39;user.taste&#39;)-&#62;radio(&#39;me_gusta&#39;)
  field(&#39;user.taste&#39;)-&#62;radio(&#39;estoy_harto_de&#39;)
  field(&#39;user.orders.0.id&#39;)-&#62;hidden

  # Fields for a collection
  my $kinfolk = field(&#39;user.kinfolk&#39;);
  for my $person (@$kinfolk) {
    $person-&#62;hidden(&#39;id&#39;)
    $person-&#62;text(&#39;name&#39;)
  }

  # Or, scope it to the &#39;user&#39; param
  my $user = fields(&#39;user&#39;)
  $user-&#62;hidden(&#39;id&#39;)
  $user-&#62;text(&#39;name&#39;)
  $user-&#62;error(&#39;name&#39;) unless $user-&#62;valid(&#39;name&#39;)
  $user-&#62;label(&#39;admin&#39;)
  $user-&#62;checkbox(&#39;admin&#39;)
  $user-&#62;password(&#39;password&#39;)
  $user-&#62;select(&#39;age&#39;, [ [X =&#62; 10], [Dub =&#62; 20] ])
  $user-&#62;file(&#39;avatar&#39;)
  $user-&#62;textarea(&#39;bio&#39;, size =&#62; &#39;10x50&#39;)

  my $kinfolk = $user-&#62;fields(&#39;kinfolk&#39;)
  for my $person (@$kinfolk) {
    $person-&#62;text(&#39;name&#39;)
    # ...
  }</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"
>&#34;field&#34;</a></code> helper with a path to the value you want to bind, and then calling the desired HTML input method</p>

<pre>  field(&#39;user.name&#39;)-&#62;text</pre>

<p>Is the same as</p>

<pre>  text_field &#39;user.name&#39;, $user-&#62;name, id =&#62; &#39;user-name&#39;</pre>

<p>(though <code>Mojolicious::Plugin::FormFields</code> sets <code>type=&#34;text&#34;</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"
>&#34;field&#34;</a></code>.</p>

<p>Some examples:</p>

<pre>  field(&#39;users.0.name&#39;)-&#62;text</pre>

<p>Is the same as</p>

<pre>  text_field &#39;users.0.name&#39;, $users-&#62;[0]-&#62;name, id =&#62; &#39;users-0-name&#39;</pre>

<p>And</p>

<pre>  field(&#39;item.orders.0.XAJ123.quantity&#39;)-&#62;text</pre>

<p>Is equivalent to</p>

<pre>  text_field &#39;item.orders.0.XAJ123.quantity&#39;, $item-&#62;orders-&#62;[0]-&#62;{XAJ123}-&#62;quantity, id =&#62; &#39;item-orders-0-XAJ123-quantity&#39;</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(&#39;book.upc&#39;, $item)-&#62;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&#39; Tag Helpers.</p>

<p>Options can also be provided</p>

<pre>  field(&#39;user.name&#39;)-&#62;text(class =&#62; &#39;input-text&#39;, &#39;data-name&#39; =&#62; &#39;xxx&#39;)</pre>

<p>See <a href="#SUPPORTED_FIELDS" class="podlinkpod"
>&#34;SUPPORTED FIELDS&#34;</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>&#39;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&#38;user.email=email&#38;id=123</code> can be accessed in your action like</p>

<pre>  my $user = $self-&#62;param(&#39;user&#39;);
  $user-&#62;{name};
  $user-&#62;{email};</pre>

<p>Other parameters can be accessed as usual</p>

<pre>  $id = $self-&#62;param(&#39;id&#39;);</pre>

<p>The flattened parameter can also be used</p>

<pre>  $name = $self-&#62;param(&#39;user.name&#39;);</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"
>&#34;fields&#34;</a></code> helper</p>

<pre>  my $user = fields(&#39;user&#39;);
  $user-&#62;text(&#39;name&#39;);
  $user-&#62;hidden(&#39;id&#39;);</pre>

<p>When using <code>fields</code> you must supply the field&#39;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(&#39;user.addresses&#39;);
  for my $addr (@$addresses) {
    # field(&#39;user.addresses.N.id&#39;)-&#62;hidden
    $addr-&#62;hidden(&#39;id&#39;);

    # field(&#39;user.addresses.N.street&#39;)-&#62;text
    $addr-&#62;text(&#39;street&#39;);

    # field(&#39;user.addresses.N.city&#39;)-&#62;select([qw|OAK PHL LAX|])
    $addr-&#62;select(&#39;city&#39;, [qw|OAK PHL LAX|]);
  }</pre>

<p>Or, for fields that are already scoped</p>

<pre>  my $user = fields(&#39;user&#39;)
  $user-&#62;hidden(&#39;id&#39;);

  my $addressess = $user-&#62;fields(&#39;addresses&#39;);
  for my $addr (@$addresses) {
    $addr-&#62;hidden(&#39;id&#39;)
    # ...
  }</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>  &#60;% for my $addr (@$addresses) {  %&#62;
    &#60;div id=&#34;&#60;%= dom_id($addr-&#62;object) %&#62;&#34;&#62;
      &#60;h3&#62;Address #&#60;%= $addr-&#62;index + 1 %&#62;&#60;/h3&#62;
      &#60;%= $addr-&#62;hidden(&#39;id&#39;) %&#62;
      ...
    &#60;/div&#62;
  &#60;% } %&#62;</pre>

<h1><a class='u'
name="VALIDATING_&#38;_FILTERING"
>VALIDATING &#38; 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-&#62;field(&#39;user.name&#39;)-&#62;is_required;
  $self-&#62;field(&#39;user.name&#39;)-&#62;filter(&#39;trim&#39;);</pre>

<p>These methods can be chained</p>

<pre>  $self-&#62;field(&#39;user.name&#39;)-&#62;is_required-&#62;filter(&#39;trim&#39;);</pre>

<p>To perform validation on a field call its <code>valid</code> method</p>

<pre>  $field = $self-&#62;field(&#39;user.name&#39;);
  $field-&#62;is_required;
  $field-&#62;valid;
  $field-&#62;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&#39;s <code>valid</code> and <code>errors</code> methods</p>

<pre>  $self-&#62;field(&#39;user.name&#39;)-&#62;is_required;
  $self-&#62;field(&#39;user.age&#39;)-&#62;is_like(qr/^\d+$/);
  $self-&#62;valid;

  my $errors = $self-&#62;errors;
  $errors-&#62;{&#39;user.name&#39;}
  # ...</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>  &#60;% unless(valid()) { %&#62;
    &#60;p&#62;Hey, fix the below errors&#60;/p&#62;
  &#60;% } %&#62;

  &#60;%= field(&#39;name&#39;)-&#62;text %&#62;
  &#60;% unless(field(&#39;name&#39;)-&#62;valid) { %&#62;
    &#60;span class=&#34;error&#34;&#62;&#60;%= field(&#39;name&#39;)-&#62;error %&#62;&#60;/span&#62;
  &#60;% } %&#62;</pre>

<p>When creating validation rules for <a href="#fields" class="podlinkpod"
>&#34;fields&#34;</a> you must pass the field name as the first argument</p>

<pre>  my $user = fields(&#39;user&#39;);
  $user-&#62;is_required(&#39;password&#39;);
  $user-&#62;is_equal(password =&#62; &#39;confirm_password&#39;);
  $user-&#62;is_long_at_least(password =&#62; 8, &#39;Mais longo caipira&#39;);</pre>

<h2><a class='u'
name="AVAILABLE_RULES_&#38;_FILTERS"
>AVAILABLE RULES &#38; 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-&#62;plugin(&#39;FormFields&#39;, methods =&#62; { valid =&#62; &#39;form_valid&#39;, errors =&#62; &#39;form_errors&#39; });
  # ...

  $self-&#62;field(&#39;user.name&#39;)-&#62;is_required;
  $self-&#62;form_valid;
  $self-&#62;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)-&#62;text
  field($name, $object)-&#62;text</pre>

<h3><a class='u'
name="Arguments"
>Arguments</a></h3>

<p><code>$name</code></p>

<p>The field&#39;s name, which can also be the path to its value in the stash. See <a href="#CREATING_FIELDS" class="podlinkpod"
>&#34;CREATING FIELDS&#34;</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"
>&#34;SUPPORTED FIELDS&#34;</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"
>&#34;COLLECTIONS&#34;</a></p>

<h2><a class='u'
name="fields"
>fields</a></h2>

<pre>  $f = fields($name)
  $f-&#62;text(&#39;address&#39;)

  $f = fields($name, $object)
  $f-&#62;text(&#39;address&#39;)</pre>

<p>Create form fields scoped to a parameter.</p>

<p>For example</p>

<pre>  % $f = fields(&#39;user&#39;)
  %= $f-&#62;select(&#39;age&#39;, [10,20,30])
  %= $f-&#62;textarea(&#39;bio&#39;)</pre>

<p>Is the same as</p>

<pre>  %= field(&#39;user.age&#39;)-&#62;select([10,20,30])
  %= field(&#39;user.bio&#39;)-&#62;textarea</pre>

<h3><a class='u'
name="Arguments"
>Arguments</a></h3>

<p>Same as <a href="#field" class="podlinkpod"
>&#34;field&#34;</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"
>&#34;SUPPORTED FIELDS&#34;</a>.</p>

<h3><a class='u'
name="Errors"
>Errors</a></h3>

<p>Same as <a href="#field" class="podlinkpod"
>&#34;field&#34;</a>.</p>

<h3><a class='u'
name="Collections"
>Collections</a></h3>

<p>See <a href="#COLLECTIONS" class="podlinkpod"
>&#34;COLLECTIONS&#34;</a></p>

<h1><a class='u'
name="SUPPORTED_FIELDS"
>SUPPORTED FIELDS</a></h1>

<h2><a class='u'
name="checkbox"
>checkbox</a></h2>

<pre>  field(&#39;user.admin&#39;)-&#62;checkbox(%options)
  field(&#39;user.admin&#39;)-&#62;checkbox(&#39;yes&#39;, %options)</pre>

<p>Creates</p>

<pre>  &#60;input type=&#34;checkbox&#34; name=&#34;user.admin&#34; id=&#34;user-admin-1&#34; value=&#34;1&#34;/&#62;
  &#60;input type=&#34;checkbox&#34; name=&#34;user.admin&#34; id=&#34;user-admin-yes&#34; value=&#34;yes&#34;/&#62;</pre>

<h2><a class='u'
name="file"
>file</a></h2>

<pre>  field(&#39;user.avatar&#39;)-&#62;file(%options);</pre>

<p>Creates</p>

<pre>  &#60;input id=&#34;user-avatar&#34; name=&#34;user.avatar&#34; type=&#34;file&#34; /&#62;</pre>

<h2><a class='u'
name="hidden"
>hidden</a></h2>

<pre>  field(&#39;user.id&#39;)-&#62;hidden(%options)</pre>

<p>Creates</p>

<pre>  &#60;input id=&#34;user-id&#34; name=&#34;user.id&#34; type=&#34;hidden&#34; value=&#34;123123&#34; /&#62;</pre>

<h2><a class='u'
name="input"
>input</a></h2>

<pre>  field(&#39;user.phone&#39;)-&#62;input($type, %options)</pre>

<p>For example</p>

<pre>  field(&#39;user.phone&#39;)-&#62;input(&#39;tel&#39;, pattern =&#62; &#39;\d{3}-\d{4}&#39;)</pre>

<p>Creates</p>

<pre>  &#60;input id=&#34;user-phone&#34; name=&#34;user.phone&#34; type=&#34;tel&#34; pattern=&#34;\d{3}-\d{4}&#34; /&#62;</pre>

<h2><a class='u'
name="label"
>label</a></h2>

<pre>  field(&#39;user.name&#39;)-&#62;label
  field(&#39;user.name&#39;)-&#62;label(&#39;Nombre&#39;, for =&#62; &#34;tu_nombre_hyna&#34;)</pre>

<p>Creates</p>

<pre>  &#60;label for=&#34;user-name&#34;&#62;Name&#60;/label&#62;
  &#60;label for=&#34;tu_nombre_hyna&#34;&#62;Nombre&#60;/label&#62;</pre>

<h2><a class='u'
name="password"
>password</a></h2>

<pre>  field(&#39;user.password&#39;)-&#62;password(%options)</pre>

<p>Creates</p>

<pre>  &#60;input id=&#34;user-password&#34; name=&#34;user.password&#34; type=&#34;password&#34; /&#62;</pre>

<h2><a class='u'
name="select"
>select</a></h2>

<pre>  field(&#39;user.age&#39;)-&#62;select([10,20,30], %options)
  field(&#39;user.age&#39;)-&#62;select([[Ten =&#62; 10], [Dub =&#62; 20], [Trenta =&#62; 30]], %options)</pre>

<p>Creates</p>

<pre>  &#60;select id=&#34;user-age&#34; name=&#34;user.age&#34;&#62;
    &#60;option value=&#34;10&#34;&#62;10&#60;/option&#62;
    &#60;option value=&#34;20&#34;&#62;20&#60;/option&#62;
    &#60;option value=&#34;30&#34;&#62;30&#60;/option&#62;
  &#60;/select&#62;

  &#60;select id=&#34;user-age&#34; name=&#34;user.age&#34;&#62;
    &#60;option value=&#34;10&#34;&#62;Ten&#60;/option&#62;
    &#60;option value=&#34;20&#34;&#62;Dub&#60;/option&#62;
    &#60;option value=&#34;30&#34;&#62;Trenta&#60;/option&#62;
  &#60;/select&#62;</pre>

<h2><a class='u'
name="radio"
>radio</a></h2>

<pre>  field(&#39;user.age&#39;)-&#62;radio(&#39;older_than_21&#39;, %options)</pre>

<p>Creates</p>

<pre>  &#60;input id=&#34;user-age-older_than_21&#34; name=&#34;user.age&#34; type=&#34;radio&#34; value=&#34;older_than_21&#34; /&#62;</pre>

<h2><a class='u'
name="text"
>text</a></h2>

<pre>  field(&#39;user.name&#39;)-&#62;text(%options)
  field(&#39;user.name&#39;)-&#62;text(size =&#62; 10, maxlength =&#62; 32)</pre>

<p>Creates</p>

<pre>  &#60;input id=&#34;user-name&#34; name=&#34;user.name&#34; value=&#34;sshaw&#34; /&#62;
  &#60;input id=&#34;user-name&#34; name=&#34;user.name&#34; value=&#34;sshaw&#34; size=&#34;10&#34; maxlength=&#34;32&#34; /&#62;</pre>

<h2><a class='u'
name="textarea"
>textarea</a></h2>

<pre>  field(&#39;user.bio&#39;)-&#62;textarea(%options)
  field(&#39;user.bio&#39;)-&#62;textarea(size =&#62; &#39;10x50&#39;)</pre>

<p>Creates</p>

<pre>  &#60;textarea id=&#34;user-bio&#34; name=&#34;user.bio&#34;&#62;Proprietary and confidential&#60;/textarea&#62;
  &#60;textarea cols=&#34;50&#34; id=&#34;user-bio&#34; name=&#34;user.bio&#34; rows=&#34;10&#34;&#62;Proprietary and confidential&#60;/textarea&#62;</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>