NAME

    Mojolicious::Plugin::FormFieldsFromJSON - create form fields based on a
    definition in a JSON file

VERSION

    version 1.03

SYNOPSIS

      # Mojolicious
      $self->plugin('FormFieldsFromJSON');
    
      # Mojolicious::Lite
      plugin 'FormFieldsFromJSON';

DESCRIPTION

    Mojolicious::Plugin::FormFieldsFromJSON is a Mojolicious plugin.

NAME

    Mojolicious::Plugin::FormFieldsFromJSON - create form fields based on a
    definition in a JSON file

VERSION

    version 0.32

CONFIGURATION

    You can configure some settings for the plugin:

      * dir

      The directory where the json files for form field configuration are
      located

        $self->plugin( 'FormFieldsFromJSON' => {
          dir => '/home/mojo/fields',
        });

      You can also pass an arrayreference with directory names. This will
      help when you store the JSON files where your templates are...

        $self->plugin( 'FormFieldsFromJSON' => {
          dir => [
            '/home/mojo/templates/admin/json',
            '/home/mojo/templates/author/json',
            '/home/mojo/templates/guest/json',
          ]
        });

      * template

      With template you can define a template for the form fields.

        $self->plugin( 'FormFieldsFromJSON' => {
          template => '<label for="<%= $id %>"><%= $label %>:</label><div><%= $field %></div>',
        });

      See Templates.

      * templates

      With template you can define type specific templates for the form
      fields.

        plugin 'FormFieldsFromJSON' => {
          templates => {
            text => '<%= $label %>: <%= $field %>',
          },
        };

      See Templates.

      * global_attributes

      With global_attributes, you can define attributes that should be set
      for every field (except hidden fields)

        plugin 'FormFieldsFromJSON' => {
          global_attributes => {
            class => 'important-field',
          },
        };

      So with this configuration

       [
          {
              "label" : "Name",
              "type" : "text",
              "name" : "name"
          },
          {
              "label" : "Background",
              "type" : "text",
              "name" : "background"
          }
       ]

      You get

           <input class="important-field" id="name" name="name" type="text" value="" />
           <input class="important-field" id="background" name="background" type="text" value="" />

      * alias

      Using aliases can help you a lot. Given you want to have several
      forms where the user can define a color (e.g. by using
      bootstrap-colorpicker), you don't want to define the special
      templates in each form. Instead you can define those fiels as type
      "color" and use an alias:

        plugin 'FormFieldsFromJSON' => {
          template  => '<%= $label %>: <%= $field %>',
          templates => {
            color => '<%= $label %> (color): <%= $field %>',
          },
          alias => {
            color => 'text',
          },
        };

      The alias defines that "color" fields are "text" fields.

      So with this configuration

       [
          {
              "label" : "Name",
              "type" : "text",
              "name" : "name"
          },
          {
              "label" : "Background",
              "type" : "color",
              "name" : "background"
          }
       ]

      You get

           <label for="name">Name:</label><div><input id="name" name="name" type="text" value="" /></div>
           <label for="background">Background (color):</label><div><input id="background" name="background" type="text" value="" /></div>

      * translate_labels

      If translate_labels is true, the labels for the templates are
      translated. You have to provide a translation_method, too.

        plugin 'FormFieldsFromJSON' => {
          template           => '<%= $label %>: <%= $field %>',
          translate_labels   => 1,
          translation_method => \&loc,
        };

      For more details see Translation.

      * translation_method

      If translate_labels is true, the labels for the templates are
      translated. You have to provide a translation_method, too.

        plugin 'FormFieldsFromJSON' => {
          template           => '<%= $label %>: <%= $field %>',
          translate_labels   => 1,
          translation_method => \&loc,
        };

      For more details see
      Translation|Mojolicious::Plugin::FormFieldsFromJSON/Translation.

      * types

      If you have written a plugin that implements a new "type" of input
      field, you can allow this type by passing types when you load the
      plugin.

        plugin 'FormFieldsFromJSON' => {
          types => {
              'testfield' => 1,
          },
        };

      Now you can use

        [
          {
            "label" : "Name",
            "type" : "testfield",
            "name" : "name"
          }
        ]

      For more details see Additional Types.

HELPER

 form_fields

    form_fields returns a string with all configured fields "translated" to
    HTML.

      $controller->form_fields( 'formname' );

    Given this configuration:

     [
        {
            "label" : "Name",
            "type" : "text",
            "name" : "name"
        },
        {
            "label" : "City",
            "type" : "text",
            "name" : "city"
        }
     ]

    You'll get

     <input id="name" name="name" type="text" value="" />
     <input id="city" name="city" type="text" value="" />

  dynamic config

    Instead of a formname, you can pass a config:

      $controller->form_fields(
        [
          {
            "label" : "Name",
            "type" : "testfield",
            "name" : "name"
          }
        ]
      );

    This way, you can build your forms dynamically (e.g. based on database
    entries).

 validate_form_fields

    This helper validates the input. It uses the
    Mojolicious::Validator::Validation and it validates all fields defined
    in the configuration file.

    For more details see Validation.

 forms

    This method returns a list of forms. That means the filenames of all
    .json files in the configured directory.

      my @forms = $controller->forms;

    The filenames are returned without the file suffix .json.

 fields

    fields() returns a list of fields (label or name).

      my @fieldnames = $controller->fields('formname');

    If your configuration looks like

     [
       {
         "label" : "Email",
         "name"  : "email",
         "type"  : "text"
       },
       {
         "name"  : "password",
         "type"  : "password"
       }
     ]

    You get

      (
        Email,
        password
      )

FIELD DEFINITIONS

    This plugin supports several form fields:

      * text

      * checkbox

      * radio

      * select

      * textarea

      * password

      * hidden

    Those fields have the following definition items in common:

      * name

      The name of the field. If you do not pass an id for the field in the
      attributes-field, the name is also taken for the field id.

      * label

      If a template is used, this value is passed for $label. If the
      translation feature is used, the label is translated.

      * type

      One of the above mentioned types. Please note, that you can add own
      types.

      * data

      For text, textarea, password and hidden this is the value for the
      field. This can be set in various ways:

      1. Data passed in the code like

          $c->form_fields( 'form', fieldname => { data => 'test' } );

      2. Data passed via stash

          $c->stash( fieldname => 'test' );

      3. Data in the request

      4. Data defined in the field configuration

      5. Data passed via stash - part two

          $c->stash( any_name => { fieldname => 'test' } );
          $c->form_fields( 'form', from_stash => 'any_name' );

      For select, checkbox and radio fields, data contains the possible
      values.

      * attributes

      Attributes of the field like "class":

        attributes => {
          class => 'button'
        }

      If global_attributes are defined, then the values are added, so that

        plugin( 'FormFieldsFromJSON' => {
          global_attributes => {
            class => 'button-danger',
          }
        });

      and the attributes field as shown, then the field has two classes:
      button and button-danger. In the field the classes mentioned in field
      config come first.

        <button class="button button-danger" ...>

EXAMPLES

    The following sections should give you an idea what's possible with
    this plugin

 text

    With type text you get a simple text input field.

  A simple text field

    This is the configuration for a simple text field:

     [
        {
            "label" : "Name",
            "type" : "text",
            "name" : "name"
        }
     ]

    And the generated form field looks like

     <input id="name" name="name" type="text" value="" />

  Set CSS classes

    If you want to set a CSS class, you can use the attributes field:

     [
        {
            "label" : "Name",
            "type" : "text",
            "name" : "name",
            "attributes" : {
                "class" : "W75px"
            }
        }
     ]

    And the generated form field looks like

     <input class="W75px" id="name" name="name" type="text" value="" />

  Text field with predefined value

    Sometimes, you want to predefine a value shown in the text field. Then
    you can use the data field:

     [
        {
            "label" : "Name",
            "type" : "text",
            "name" : "name",
            "data" : "default value"
        }
     ]

    This will generate this input field:

      <input id="name" name="name" type="text" value="default value" />

 select

  Simple: Value = Label

    When you have a list of values for a select field, you can define an
    array reference:

      [
        {
          "type" : "select",
          "name" : "language",
          "data" : [
            "de",
            "en"
          ]
        }
      ]

    This creates the following select field:

      <select id="language" name="language">
          <option value="de">de</option>
          <option value="en">en</option>
      </select>

  Preselect a value

    You can define

      [
        {
          "type" : "select",
          "name" : "language",
          "data" : [
            "de",
            "en"
          ],
          "selected" : "en"
        }
      ]

    This creates the following select field:

      <select id="language" name="language">
          <option value="de">de</option>
          <option value="en" selected="selected">en</option>
      </select>

    If a key named as the select exists in the stash, those values are
    preselected (this overrides the value defined in the .json):

      $c->stash( language => 'en' );

    and

      [
        {
          "type" : "select",
          "name" : "language",
          "data" : [
            "de",
            "en"
          ]
        }
      ]

    This creates the following select field:

      <select id="language" name="language">
          <option value="de">de</option>
          <option value="en" selected="selected">en</option>
      </select>

  Multiselect

      [
        {
          "type" : "select",
          "name" : "languages",
          "data" : [
            "de",
            "en",
            "cn",
            "jp"
          ],
          "multiple" : 1,
          "size" : 3
        }
      ]

    This creates the following select field:

      <select id="languages" name="languages" multiple="multiple" size="3">
          <option value="cn">cn</option>
          <option value="de">de</option>
          <option value="en">en</option>
          <option value="jp">jp</option>
      </select>

  Preselect multiple values

      [
        {
          "type" : "select",
          "name" : "languages",
          "data" : [
            "de",
            "en",
            "cn",
            "jp"
          ],
          "multiple" : 1,
          "selected" : [ "en", "de" ]
        }
      ]

    This creates the following select field:

      <select id="language" name="language">
          <option value="cn">cn</option>
          <option value="de" selected="selected">de</option>
          <option value="en" selected="selected">en</option>
          <option value="jp">jp</option>
      </select>

  Values != Label

      [
        {
          "type" : "select",
          "name" : "language",
          "data" : {
            "de" : "German",
            "en" : "English"
          }
        }
      ]

    This creates the following select field:

      <select id="language" name="language">
          <option value="en">English</option>
          <option value="de">German</option>
      </select>

  Option groups

      [
        {
          "type" : "select",
          "name" : "language",
          "data" : {
            "EU" : {
              "de" : "German",
              "en" : "English"
            },
            "Asia" : {
              "cn" : "Chinese",
              "jp" : "Japanese"
            }
          }
        }
      ]

    This creates the following select field:

      <select id="language" name="language">
          <option value="en">English</option>
          <option value="de">German</option>
      </select>

  Disable values

      [
        {
          "type" : "select",
          "name" : "languages",
          "data" : [
            "de",
            "en",
            "cn",
            "jp"
          ],
          "multiple" : 1,
          "disabled" : [ "en", "de" ]
        }
      ]

    This creates the following select field:

      <select id="language" name="language">
          <option value="cn">cn</option>
          <option value="de" disabled="disabled">de</option>
          <option value="en" disabled="disabled">en</option>
          <option value="jp">jp</option>
      </select>

 radio

    For radiobuttons, you can use two ways: You can either configure form
    fields for each value or you can define a list of values in the data
    field. With the first way, you can create radiobuttons where the
    template (if any defined) is applied to each radiobutton. With the
    second way, the radiobuttons are handled as one single field in the
    template.

  A single radiobutton

    Given the configuration

     [
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "data" : "internal"
        }
     ]

    You get

  Two radiobuttons configured separately

    With the configuration

     [
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "data" : "internal"
        },
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "data" : "external"
        }
     ]

    You get

  Two radiobuttons as a group

    And with

     [
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "data" : ["internal", "external" ]
        }
     ]

    You get

  Two radiobuttons configured separately - with template

    Define template:

      plugin 'FormFieldsFromJSON' => {
        dir      => './conf',
        template => '<%= $label %>: <%= $form %>';
      };

    Config:

     [
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "data" : "internal"
        },
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "data" : "external"
        }
     ]

    Fields:

      Name: <input id="type" name="type" type="radio" value="internal" />
      
      
      
      Name: <input id="type" name="type" type="radio" value="external" />

  Two radiobuttons as a group - with template

    Same template definition as above, but given this field config:

     [
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "data" : ["internal", "external" ]
        }
     ]

    You get this:

      Name: <input id="type" name="type" type="radio" value="internal" />
      <input id="type" name="type" type="radio" value="external" />

  Two radiobuttons - one checked

    Config:

     [
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "data" : ["internal", "external" ],
            "selected" : ["internal"]
        }
     ]

    Field:

      <input checked="checked" id="type" name="type" type="radio" value="internal" />
      <input id="type" name="type" type="radio" value="external" />

  Radiobuttons with HTML after every element

    When you want to add some HTML code after every element - e.g. a <br />
    - you can use after_element

     [
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "after_element" : "<br />",
            "data" : ["internal", "external" ]
        }
     ]

    Fields:

      <input id="type" name="type" type="radio" value="internal" />
      <br /><input id="type" name="type" type="radio" value="external" />
      <br />

  Radiobuttons with values shown as label

    When you want to show the value as a label, you can use show_value.

     [
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "show_value" : 1,
            "data" : ["internal", "external" ]
        }
     ]

    Creates

      <input id="type" name="type" type="radio" value="internal" /> internal
      <input id="type" name="type" type="radio" value="external" /> external

  Radiobuttons with translated values for "sublabels"

    If you want to show the "sublabels" and want them to be translated, you
    can use translate_sublabels

     [
        {
            "label" : "Name",
            "type" : "radio",
            "name" : "type",
            "show_value" : 1,
            "translate_sublabels" : 1,
            "data" : ["internal", "external" ]
        }
     ]

    Given this plugin is used this way:

      plugin 'FormFieldsFromJSON' => {
          dir => File::Spec->catdir( dirname( __FILE__ ) || '.', 'conf' ),
          translation_method => \&loc,
      };
      
      sub loc {
          my ($c, $value) = @_;
      
          my %translation = ( internal => 'intern', external => 'extern' );
          return $translation{$value} // $value;
      };

    You'll get

      <input id="type" name="type" type="radio" value="internal" /> intern
      <input id="type" name="type" type="radio" value="external" /> extern

 checkbox

    For checkboxes, you can use two ways: You can either configure form
    fields for each value or you can define a list of values in the data
    field. With the first way, you can create checkboxes where the template
    (if any defined) is applied to each checkbox. With the second way, the
    checkboxes are handled as one single field in the template.

  A single checkbox

    Given the configuration

     [
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "data" : "internal"
        }
     ]

    You get

  Two checkboxes configured separately

    With the configuration

     [
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "data" : "internal"
        },
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "data" : "external"
        }
     ]

    You get

  Two checkboxes as a group

    And with

     [
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "data" : ["internal", "external" ]
        }
     ]

    You get

  Two checkboxes configured separately - with template

    Define template:

      plugin 'FormFieldsFromJSON' => {
        dir      => './conf',
        template => '<%= $label %>: <%= $form %>';
      };

    Config:

     [
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "data" : "internal"
        },
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "data" : "external"
        }
     ]

    Fields:

      Name: <input id="type" name="type" type="checkbox" value="internal" />
      
      
      
      Name: <input id="type" name="type" type="checkbox" value="external" />

  Two checkboxes as a group - with template

    Same template definition as above, but given this field config:

     [
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "data" : ["internal", "external" ]
        }
     ]

    You get this:

      Name: <input id="type" name="type" type="checkbox" value="internal" />
      <input id="type" name="type" type="checkbox" value="external" />

  Two checkboxes - one checked

    Config:

     [
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "data" : ["internal", "external" ],
            "selected" : ["internal"]
        }
     ]

    Field:

      <input checked="checked" id="type" name="type" type="checkbox" value="internal" />
      <input id="type" name="type" type="checkbox" value="external" />

  Checkboxes with HTML after every element

    When you want to add some HTML code after every element - e.g. a <br />
    - you can use after_element

     [
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "after_element" : "<br />",
            "data" : ["internal", "external", "unknown" ]
        }
     ]

    Fields:

      <input id="type" name="type" type="checkbox" value="internal" />
      <br /><input id="type" name="type" type="checkbox" value="external" />
      <br /><input id="type" name="type" type="checkbox" value="unknown" />
      <br />

  Checkboxes with values shown as label

    When you want to show the value as a label, you can use show_value.

     [
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "show_value" : 1,
            "data" : ["internal", "external" ]
        }
     ]

    Creates

      <input id="type" name="type" type="checkbox" value="internal" /> internal
      <input id="type" name="type" type="checkbox" value="external" /> external

  Checkboxes with translated values for "sublabels"

    If you want to show the "sublabels" and want them to be translated, you
    can use translate_sublabels

     [
        {
            "label" : "Name",
            "type" : "checkbox",
            "name" : "type",
            "show_value" : 1,
            "translate_sublabels" : 1,
            "data" : ["internal", "external" ]
        }
     ]

    Given this plugin is used this way:

      plugin 'FormFieldsFromJSON' => {
          dir => File::Spec->catdir( dirname( __FILE__ ) || '.', 'conf' ),
          translation_method => \&loc,
      };
      
      sub loc {
          my ($c, $value) = @_;
      
          my %translation = ( internal => 'intern', external => 'extern' );
          return $translation{$value} // $value;
      };

    You'll get

      <input id="type" name="type" type="checkbox" value="internal" /> intern
      <input id="type" name="type" type="checkbox" value="external" /> extern

 textarea

    This type is very similar to text.

  A simple textarea

    This is the configuration for a simple text field:

     [
        {
            "type" : "textarea",
            "name" : "message",
            "data" : "Current message"
        }
     ]

    And the generated form field looks like

      <textarea id="message" name="message">Current message</textarea>

  A textarea with defined number of columns and rows

    This is the configuration for a simple text field:

     [
        {
            "type" : "textarea",
            "name" : "message",
            "data" : "Current message",
            "attributes" : {
                "cols" : 80,
                "rows" : 10
            }
        }
     ]

    And the generated textarea looks like

      <textarea cols="80" id="message" name="message" rows="10">Current message</textarea>

 password

    This type is very similar to text. You can use the very same settings
    as for text fields, so we show only a simple example here:

  A simple password field

    This is the configuration for a simple text field:

     [
        {
            "type" : "password",
            "name" : "user_password"
        }
     ]

    And the generated form field looks like

     <input id="user_password" name="password" type="password" value="" />

Templates

    Especially when you work with frameworks like Bootstrap, you want to
    your form fields to look nice. For that the form fields are within divs
    or other HTML elements.

    To make your life easier, you can define templates. Either a "global"
    one, a type specific template or a template for one field.

    For hidden fields, no template is applied!

 A global template

    When you load the plugin this way

      $self->plugin( 'FormFieldsFromJSON' => {
        template => '<label for="<%= $id %>"><%= $label %>:</label><div><%= $field %></div>',
      });

    and have a configuration that looks like

    You get

      <label for="name">Name:</label><div><input id="name" name="name" type="text" value="" /></div>
      
       
      <label for="password">Password:</label><div><input id="password" name="password" type="text" value="" /></div>

 A type specific template

    When you want to use a different template for select fields, you can
    use a different template for that kind of fields:

      plugin 'FormFieldsFromJSON' => {
        dir       => File::Spec->catdir( dirname( __FILE__ ) || '.', 'conf' ),
        template  => '<label for="<%= $id %>"><%= $label %>:</label><div><%= $field %></div>',
        templates => {
          select => '<%= $label %>: <%= $field %>',
        },
      };

    With a configuration file like

     [
        {
            "label" : "Name",
            "type" : "text",
            "name" : "name"
        }
        {
            "label" : "Country",
            "type" : "select",
            "name" : "country",
            "data" : [ "au" ]
        }
     ]

    You get

      <label for="name">Name:</label><div><input id="name" name="name" type="text" value="" /></div>
      
       
      Country: <select id="country" name="country"><option value="au">au</option></select>

 A field specific template

    When you want to use a different template for a specific field, you can
    use the template field in the configuration file.

      plugin 'FormFieldsFromJSON' => {
        dir       => File::Spec->catdir( dirname( __FILE__ ) || '.', 'conf' ),
        template  => '<label for="<%= $id %>"><%= $label %>:</label><div><%= $field %></div>',
      };

    With a configuration file like

     [
        {
            "label" : "Name",
            "type" : "text",
            "name" : "name"
        }
        {
            "label" : "Country",
            "type" : "select",
            "name" : "country",
            "data" : [ "au" ],
            "template" : "<%= $label %>: <%= $field %>"
        }
     ]

    You get

      <label for="name">Name:</label><div><input id="name" name="name" type="text" value="" /></div>
      
       
      Country: <select id="country" name="country"><option value="au">au</option></select>

 Template variables

    You get three template variables for free:

      * $label

      If a label is defined in the field configuration

      * $field

      The form field (HTML)

      * $id

      The id for the field. If no id is defined, the name of the field is
      set.

Validation

    You can define some validation rules in your config file. And when you
    call validate_form_fields, the fields defined in the configuration file
    are validated.

    Mojolicious::Validator::Validation is shipped with some basic
    validation checks:

      * in

      * size

      * like

      * equal_to

    There is Mojolicious::Plugin::AdditionalValidationChecks with some more
    basic checks. And you can also define your own checks.

    The validation field is a hashref where the name of the check is the
    key and the parameters for the check can be defined in the value:

      "validation" : {
          "size" : [ 2, 5 ]
      },

    This will call ->size(2,5). If you want to pass a single parameter, you
    can set a scalar:

      "validation" : {
          "equal_to" : "foo"
      },

    Validation checks are done in asciibetical order.

    You can also use the filters:

      "validation" : {
          "size" : [ 2, 5 ],
          "filters" : [ "trim" ]
      },

 Check a string for its length

    This is a simple check for the length of a string

     [
        {
            "label" : "Name",
            "type" : "text",
            "validation" : {
                "size" : [ 2, 5 ]
            },
            "name" : "name"
        }
     ]

    Then you can call validate_form_fields:

      my %errors = $c->validate_form_fields( $config_name );

    In the returned hash, you get the fieldnames as keys where a validation
    check fails.

 A mandatory string

    If you have mandatory fields, you can define them as required

     [
        {
            "label" : "Name",
            "type" : "text",
            "validation" : {
                "required" : "name"
            },
            "name" : "name"
        }
     ]

 Provide your own error message

    With the simple configuration seen above, the %error hash contains the
    value "1" for each invalid field. If you want to get a better error
    message, you can define a hash in the validation config

     [
        {
            "label" : "Name",
            "type" : "text",
            "validation" : {
                "like" : { "args" : [ "es" ], "msg" : "text must contain 'es'" },
                "size" : { "args" : [ 2, 5 ], "msg" : "length must be between 2 and 5 chars" }
            },
            "name" : "name"
        }
     ]

    Examples:

      text   | error
      -------+---------------------------------
      test   |
      t      | text must contain 'es'
      tester | length must be between 2 and 5 chars

Translation

    Most webapplications nowadays are internationalized, therefor this
    module provides some support for translations.

    If translate_labels is set to a true value, a template is used and
    translation_method is given, the labels are translated.

 translation_method

    translation_method has to be a reference to a subroutine.

  An example for translation

    Load and configure the plugin:

      plugin 'FormFieldsFromJSON' => {
        dir                => File::Spec->catdir( dirname( __FILE__ ) || '.', 'conf' ),
        template           => '<label for="<%= $id %>"><%= $label %>:</label><div><%= $field %></div>',
        translate_labels   => 1,
        translation_method => \&loc,
      };

    The translation method gets two parameters:

      * the controller object

      * the label

      sub loc {
          my ($c, $value) = @_;
      
          my %translation = ( Address => 'Adresse' );
          return $translation{$value} // $value;
      };

    This can be a more complex subroutine that makes use of any translation
    framework.

    Given this field configuration file:

     [
        {
            "label" : "Address",
            "type" : "text",
            "name" : "name"
        }
     ]

    You'll get

      <label for="name">Adresse:</label><div><input id="name" name="name" type="text" value="" /></div>

 Internationalization

    There is more about internationalization (i18n) than just translation.
    There are dates, ranges, order of characters etc. But that can't be
    covered within this single module. There are more Mojolicious plugins
    that provide more features about i18n:

      * Mojolicious::Plugin::I18N

      * Mojolicious::Plugin::TagHelpersI18N

      * Mojolicious::Plugin::I18NUtils

      * Mojolicious::Plugin::CountryDropDown

    You can combine these plugins with this plugin. An example is available
    at the code repository
    <http://github.com/reneeb/Mojolicious-Plugin-FormFieldsFromJSON/tree/master/example>.

 New Types

    The field types supported by this plugin might not enough for you. Then
    you can create your own plugin and add new types. For example, dates in
    OTRS <http://otrs.org> are shown as three dropdowns: one for the day,
    one for the month and finally one for the year.

    Wouldn't it be nice to define only one field in your config and the
    rest is DWIM (Do what I mean)? It would.

    So you can write your own Mojolicious plugin where the register
    subroutine does nothing. And you define a subroutine called
    Mojolicious::Plugin::FormFieldsFromJSON::_date where those dropdowns
    are created.

    Then just do:

      plugin 'WhateverYouHaveChosen';
      plugin 'FormFieldsFromJSON' => {
        types => {
            'date' => 1,
        },
      };

    Now you can use

      [
        {
          "label" : "Release date",
          "type" : "date",
          "name" : "release"
        }
      ]

    The subroutine gets these parameters:

      * The plugin object (Mojolicious::Plugin::FormFieldsFromJSON object)

      So you can use the methods defined in this plugin, for example to
      create dropdowns, textfields, ...

      * The controller object (Whatever controller called form_fields
      method)

      So you can use all the Mojolicious power!

      * The field config

      Whatever you defined in you .json config file for that field

      * A params hash

      Whatever is passed as parameters to the form_fields method.

    As an example, you can see
    Mojolicious::Plugin::FormFieldsFromJSON::Date.

SEE ALSO

    Mojolicious, Mojolicious::Guides, http://mojolicio.us.

AUTHOR

    Renee Baecker <reneeb@cpan.org>

COPYRIGHT AND LICENSE

    This software is Copyright (c) 2016 by Renee Baecker.

    This is free software, licensed under:

      The Artistic License 2.0 (GPL Compatible)

AUTHOR

    Renee Baecker <reneeb@cpan.org>

COPYRIGHT AND LICENSE

    This software is Copyright (c) 2018 by Renee Baecker.

    This is free software, licensed under:

      The Artistic License 2.0 (GPL Compatible)