NAME
HTML::FormHandler::Field - base class for fields
VERSION
version 0.36003
SYNOPSIS
Instances of Field subclasses are generally built by HTML::FormHandler from 'has_field' declarations or the field_list, but they can also be constructed using new (usually for test purposes).
use HTML::FormHandler::Field::Text;
my $field = HTML::FormHandler::Field::Text->new( name => $name, ... );
In your custom field class:
package MyApp::Field::MyText;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Field::Text';
has 'my_attribute' => ( isa => 'Str', is => 'rw' );
apply [ { transform => sub { ... } },
{ check => ['fighter', 'bard', 'mage' ], message => '....' }
];
1;
DESCRIPTION
This is the base class for form fields. The 'type' of a field class is used in the FormHandler field_list or has_field to identify which field class to load. If the type is not specified, it defaults to Text.
There are two rough categories of Field classes: those that do extra processing and those that are simple validators. The 'Compound', 'Repeatable', and 'Select' fields are fields that are functional.
A number of field classes are provided by the distribution. The basic for-validation (as opposed to 'functional') field types are:
Text
Integer
Boolean
These field types alone would be enough for most applications, since the equivalent of the others could be defined using field attributes, custom validation methods, and applied actions. There is some benefit to having descriptive names, of course, and if you have multiple fields requiring the same validation, defining a custom field class may be a good idea.
Inheritance hierarchy of the distribution's field classes:
Compound
Repeatable
Text
Money
Password
Integer
PosInteger
TextArea
HtmlArea
Select
Multiple
IntRange
Hour
Minute
MonthDay
Month
Second
Year
MonthName
Weekday
Boolean
Checkbox
DateMDY
DateTime
Email
PrimaryKey
See the documentation or source for the individual fields.
Many field classes contain only a list of constraints and transformations to apply. Some use the 'validate' method, which is called after the actions are applied. Some build a custom select list using 'build_options'.
ATTRIBUTES
Names, types, accessor
- name
-
The name of the field. Used in the HTML form. Often a db accessor. The only required attribute.
- type
-
The class or type of the field. The 'type' of HTML::FormHandler::Field::Money is 'Money'. Classes that you define yourself are prefixed with '+'.
- accessor
-
If the name of your field is different than your database accessor, use this attribute to provide the accessor.
- full_name
-
The name of the field with all parents:
'event.start_date.month'
- full_accessor
-
The field accessor with all parents
- html_name
-
The full_name plus the form name if 'html_prefix' is set.
- input_param
-
By default we expect an input parameter based on the field name. This allows you to look for a different input parameter.
Field data
- inactive, is_inactive, is_active
-
Set the 'inactive' attribute to 1 if this field is inactive. The 'inactive' attribute that isn't set or is set to 0 will make a field 'active'. This provides a way to define fields in the form and selectively set them to inactive. There is also an '_active' attribute, for internal use to indicate that the field has been activated/inactivated on 'process' by the form's 'active'/'inactive' attributes.
You can use the is_inactive and is_active methods to check whether this particular field is active.
if( $form->field('foo')->is_active ) { ... }
- input
-
The input string from the parameters passed in.
- value
-
The value as it would come from or go into the database, after being acted on by transforms. Used to construct the
$form->values
hash. Validation and constraints act on 'value'. - fif
-
Values used to fill in the form. Read only. Use a deflation to get from 'value' to 'fif' if an inflator was used. (Deflations can be done in two different places. Set 'deflate_to' => 'fif' to deflate in fillinform'.)
[% form.field('title').fif %]
- init_value
-
Initial value populated by init_from_object. You can tell if a field has changed by comparing 'init_value' and 'value'. Read only.
- input_without_param
-
Input for this field if there is no param. Needed for checkbox, since an unchecked checkbox does not return a parameter.
Form, parent
- form
-
A reference to the containing form.
- parent
-
A reference to the parent of this field. Compound fields are the parents for the fields they contain.
Errors
- errors
-
Returns the error list for the field. Also provides 'num_errors', 'has_errors', 'push_errors' and 'clear_errors' from Array trait. Use 'add_error' to add an error to the array if you want to use a MakeText language handle. Default is an empty list.
- add_error
-
Add an error to the list of errors. If $field->form is defined then process error message as Maketext input. See $form->language_handle for details. Returns undef.
return $field->add_error( 'bad data' ) if $bad;
- error_fields
-
Compound fields will have an array of errors from the subfields.
Attributes for creating HTML
There's a generic 'html_attr' hashref attribute that can be used to set arbitrary HTML attributes on a field's input tag.
has_field 'foo' => ( html_attr => { readonly => 1, my_attr => 'abc' } );
The 'label_attr' hashref is for label attributes, and the 'wrapper_attr' is for attributes on the wrapping element (a 'div' for the standard 'simple' wrapper).
The javascript value of the javascript attribute is entered completely.
javascript - for a Javascript string
The following are used in rendering HTML, but are handled specially.
label - Text label for this field. Defaults to ucfirst field name.
id - Useful for javascript (default is html_name. to prefix with
form name, use 'html_prefix' in your form)
render_filter - Coderef for filtering fields before rendering. By default
changes >, <, &, " to the html entities
The order attribute may be used to set the order in which fields are rendered.
order - Used for sorting errors and fields. Built automatically,
but may also be explicitly set
The following are deprecated. Use 'html_attr', 'label_attr', and 'wrapper_attr' instead.
css_class - instead use wrapper_attr => { class => '...' }
input_class - instead use html_attr => { class => '...' }
title - instead use html_attr => { title => '...' }
style - instead use html_attr => { style => '...' }
disabled - instead use html_attr => { disabled => 'disabled' }
tabindex - instead use html_attr => { tabindex => 1 }
readonly - instead use html_attr => { readonly => 'readonly' }
Rendering of the various HTML attributes is done by calling the 'process_attrs' function (from HTML::FormHandler::Render::Util) and passing in a method that adds in error classes, provides backward compatibility with the deprecated attributes, etc.
attribute hashref wrapping method
================= ================
html_attr attributes
label_attr label_attributes
wrapper_attr wrapper_attributes
In addition, these 'wrapping method' call a hook method in the form class, 'field_html_attributes' which you can use to customize and localize the various attributes.
sub field_html_attributes {
my ( $self, $field, $type, $attr ) = @_;
$attr->{class} = 'label' if $type eq 'label';
}
The 'process_attrs' function will handle an array of strings, such as for the 'class' attribute.
html5_type_attr [string]
This string is used when rendering the input tag as the value for the type attribute. It is used when the form has the is_html5 flag on.
widget
The 'widget' attribute is used in rendering, so if you are not using FormHandler's rendering facility, you don't need this attribute. It is intended for use in generating HTML, in templates and the rendering roles, and is used in HTML::FormHandler::Render::Simple. Fields of different type can use the same widget.
This attribute is set in the field classes, or in the fields defined in the form. If you want a new widget type, use a new name and provide a 'widget_<name>'
method in your copy of Render::Simple or in your form class.
If you are using a template based rendering system you will want to create a widget template. (see HTML::FormHandler::Manual::Templates)
If you are using the widget roles, you can specify the widget with the short class name instead.
Widget types for the provided field classes:
Widget : Field classes
---------------:-----------------------------------
text (Text) : Text, Integer
checkbox (Checkbox) : Checkbox, Boolean
radio_group
(RadioGroup) : Select, Multiple, IntRange (etc)
select (Select) : Select, Multiple, IntRange (etc)
checkbox_group
(CheckboxGroup) : Multiple select
textarea (Textarea) : TextArea, HtmlArea
compound (Compound) : Compound, Repeatable, DateTime
password (Password) : Password
hidden (Hidden) : Hidden
submit (Submit) : Submit
reset (Reset) : Reset
no_render (NoRender) :
upload (Upload) : Upload
Widget roles are automatically applied to field classes unless they already have a 'render' method. Render::Simple will fall back to doing $field->render
if the corresponding widget method does not exist.
You can create your own widget roles and specify the namespace in 'widget_name_space'. In the form:
has '+widget_name_space' => ( default => sub { ['MyApp::Widget'] } );
If you want to use a fully specified role name for a widget, you can prefix it with a '+':
widget => '+MyApp::Widget::SomeWidget'
For more about widgets, see HTML::FormHandler::Manual::Rendering.
Flags
password - prevents the entered value from being displayed in the form
writeonly - The initial value is not taken from the database
noupdate - Do not update this field in the database (does not appear in $form->value)
Form methods for fields
These provide the name of a method in a form (not the field ) which will act on a particular field.
- set_validate
-
Specify a form method to be used to validate this field. The default is
'validate_' . $field->name
. Periods in field names will be replaced by underscores, so that the field 'addresses.city' will use the 'validate_addresses_city' method for validation.has_field 'title' => ( isa => 'Str', set_validate => 'check_title' ); has_field 'subtitle' => ( isa => 'Str', set_validate => 'check_title' );
- set_default
-
The name of the method in the form that provides a field's default value. Default is
'default_' . $field->name
. Periods replaced by underscores. - default
-
Provide an initial value just like the 'set_default' method, except in the field declaration:
has_field 'bax' => ( default => 'Default bax' );
FormHandler has flipped back and forth a couple of times about whether a default specified in the has_field definition should override values provided in an initial item or init_object. Sometimes people want one behavior, and sometimes the other. Now 'default' does *not* override.
If you pass in a model object with
item => $row
or an initial object withinit_object => {....}
the values in that object will be used instead of values provided in the field definition with 'default' or 'default_fieldname'. If you want defaults that override the item/init_object, you can use the form flags 'use_defaults_over_obj' and 'use_init_obj_over_item'.You could also put your defaults into your row or init_object instead.
- default_over_obj
-
This is deprecated; look into using 'use_defaults_over_obj' or 'use_init_obj_over_item' flags instead. They allow using the standard 'default' attribute.
Allows setting defaults which will override values provided with an item/init_object.
has_field 'quux' => ( default_over_obj => 'default quux' );
At this time there is no equivalent of 'set_default', but the type of the attribute is not defined so you can provide default values in a variety of other ways, including providing a trait which does 'build_default_over_obj'. For examples, see tests in the distribution.
Constraints and Validations
Constraints set in attributes
- required
-
Flag indicating whether this field must have a value
- unique
-
For DB field - check for uniqueness. Action is performed by the DB model.
- messages
-
messages => { required => '...', unique => '...' }
Set messages created by FormHandler by setting in the 'messages' hashref. Some field subclasses have additional settable messages.
required: Error message text added to errors if required field is not present The default is "Field <field label> is required".
unique: message for when 'unique' is set, but field is not unique
- range_start
- range_end
-
Field values are validated against the specified range if one or both of range_start and range_end are set and the field does not have 'options'.
The IntRange field uses this range to create a select list with a range of integers.
In a FormHandler field_list
age => { type => 'Integer', range_start => 18, range_end => 120, }
- not_nullable
-
Fields that contain 'empty' values such as '' are changed to undef in the validation process. If this flag is set, the value is not changed to undef. If your database column requires an empty string instead of a null value (such as a NOT NULL column), set this attribute.
has_field 'description' => ( type => 'TextArea', not_nullable => 1, );
This attribute is also used when you want an empty array to stay an empty array and not be set to undef.
apply
Use the 'apply' keyword to specify an ArrayRef of constraints and coercions to be executed on the field at validate_field time.
has_field 'test' => (
apply => [ 'MooseType',
{ check => sub {...}, message => { } },
{ transform => sub { ... lc(shift) ... } }
],
);
In general the action can be of three types: a Moose type (which is represented by its name), a transformation (which is a callback called on the value of the field), or a constraint ('check') which performs a 'smart match' on the value of the field. Currently we implement the smart match in our code - but in the future when Perl 5.10 is more widely used we'll switch to the core http://search.cpan.org/~rgarcia/perl-5.10.0/pod/perlsyn.pod#Smart_matching_in_detail smart match operator.
The Moose type action first tries to coerce the value - then it checks the result, so you can use it instead of both constraints and tranformations - TIMTOWTDI. For most constraints and transformations it is your choice as to whether you use a Moose type or use a 'check' or 'transform'.
All three types define a message to be presented to the user in the case of failure. Messages are passed to Locale::MakeText, and can either be simple strings or an array suitable for MakeText, such as:
message => ['Email should be of the format [_1]',
'someuser@example.com' ]
Transformations and coercions are called in an eval to catch the errors. Warnings are trapped in a sigwarn handler.
All the actions are called in the order that they are defined, so that you can check constraints after transformations and vice versa. You can weave all three types of actions in any order you need. The actions specified with 'apply' will be stored in an 'actions' array.
To declare actions inside a field class use HTML::FormHandler::Moose and 'apply' sugar:
package MyApp::Field::Test;
use HTML::FormHandler::Moose;
extends 'HTML::FormHandler::Field;
apply [ 'SomeConstraint', { check => ..., message => .... } ];
1;
Actions specified with apply are cumulative. Actions may be specified in field classes and additional actions added in the 'has_field' declaration.
In addition to being a string, Messages may be arrayrefs, for localization, or coderefs, which will be passed a reference to the field and the original value.
apply [ { check => ['abc'], message => \&err_message } ];
sub err_message {
my ( $value, $field ) = @_;
return $field->name . ": must .... ";
}
You can see examples of field classes with 'apply' actions in the source for HTML::FormHandler::Field::Money and HTML::FormHandler::Field::Email, and in t/constraints.t.
Moose types for constraints and transformations
Moose types can be used to do both constraints and transformations. If a coercion exists it will be applied, resulting in a transformation. You can use type constraints form MooseX::Types> libraries or defined using Moose::Util::TypeConstraints.
A Moose type defined with Moose::Util::TypeConstraints: subtype 'MyStr' => as 'Str' => where { /^a/ };
This is a simple constraint checking if the value string starts with the letter 'a'.
Another Moose type: subtype 'MyInt' => as 'Int'; coerce 'MyInt' => from 'MyStr' => via { return $1 if /(\d+)/ };
This type contains a coercion.
You can use them in a field like this (types defined with MooseX::Types would not be quoted):
has_field 'some_text_to_int' => (
apply => [ 'MyStr', 'MyInt' ]
);
This will check if the field contains a string starting with 'a' - and then coerce it to an integer by extracting the first continuous string of digits.
If the error message returned by the Moose type is not suitable for displaying in a form, you can define a different error message by using the 'type' and 'message' keys in a hashref:
apply => [ { type => 'MyStr', message => 'Not a valid value' } ];
Non-Moose checks and transforms
A simple 'check' constraint uses the 'check' keyword pointing to a coderef, a regular expression, or an array of valid values, plus a message.
A 'check' coderef will be passed the current value of the field. It should return true or false:
has_field 'this_num' => (
apply => [
{
check => sub { if ( $_[0] =~ /(\d+)/ ) { return $1 > 10 } },
message => 'Must contain number greater than 10',
}
]
);
A 'check' regular expression:
has_field 'some_text' => (
apply => [ { check => qr/aaa/, message => 'Must contain aaa' } ],
);
A 'check' array of valid values:
has_field 'more_text' => (
apply => [ { check => ['aaa', 'bbb'], message => 'Must be aaa or bbb' } ]
);
A simple transformation uses the 'transform' keyword and a coderef. The coderef will be passed the current value of the field and should return a transformed value.
has_field 'sprintf_filter' => (
apply => [ { transform => sub{ sprintf '<%.1g>', $_[0] } } ]
);
trim
An action to trim the field. By default this contains a transform to strip beginning and trailing spaces. Set this attribute to null to skip trimming, or supply a different transform.
trim => { transform => sub {
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
} }
trim => { type => MyTypeConstraint }
Trimming is performed before any other defined actions.
deflation, deflate
A 'deflation' is a coderef that will convert from an inflated value back to a flat data representation suitable for displaying in an HTML field. If deflation is defined for a field it is automatically used for data that is taken from the database.
has_field 'my_date_time' => (
type => 'Compound',
apply => [ { transform => sub{ DateTime->new( $_[0] ) } } ],
deflation => sub { { year => $_[0]->year, month => $_[0]->month, day => $_[0]->day } },
fif_from_value => 1,
);
has_field 'my_date_time.year';
has_field 'my_date_time.month';
has_field 'my_date_time.day';
You can also use a 'deflate' method in a custom field class. See the Date field for an example. If the deflation requires data that may vary (such as a format) string and thus needs access to 'self', you would need to use the deflate method since the deflation coderef is only passed the current value of the field
Normally if you have a deflation, you will need a matching inflation, which can be supplied via a 'transform' action. When using a 'transform', the 'value' hash only contains reliably inflated values after validation has been performed, since inflation is performed at validation time.
Deflation can be done at two different places: transforming the value that's saved from the initial_object/item, or when retrieving the 'fif' (fill-in-form) value that's displayed in the HTML form. The default is deflate_to => 'value'
. To deflate when getting the 'fif' value set 'deflate_to' to 'fif'. (See t/deflate.t for examples.)
Processing and validating the field
validate_field
This is the base class validation routine. Most users will not do anything with this. It might be useful for method modifiers, if you want code that executed before or after the validation process.
validate
This field method can be used in addition to or instead of 'apply' actions in custom field classes. It should validate the field data and set error messages on errors with $field->add_error
.
sub validate {
my $field = shift;
my $value = $field->value;
return $field->add_error( ... ) if ( ... );
}
AUTHOR
FormHandler Contributors - see HTML::FormHandler
COPYRIGHT AND LICENSE
This software is copyright (c) 2012 by Gerda Shank.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.