NAME
Mojolicious::Plugin::FormFieldsFromJSON - create form fields based on a definition in a JSON file
VERSION
version 0.08
SYNOPSIS
# Mojolicious
$self->plugin('FormFieldsFromJSON');
# Mojolicious::Lite
plugin 'FormFieldsFromJSON';
DESCRIPTION
Mojolicious::Plugin::FormFieldsFromJSON is a Mojolicious plugin.
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', });
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.
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="" />
validate_form_fields
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:
label
type
data
attributes
Attributes of the field like "class"
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 seperately
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 seperately - 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" />
checkbox
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 div
s 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.
SEE ALSO
Mojolicious, Mojolicious::Guides, http://mojolicio.us.
AUTHOR
Renee Baecker <reneeb@cpan.org>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2014 by Renee Baecker.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)