File Coverage

blib/lib/HTML/FormHandler/Field.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package HTML::FormHandler::Field;
2             # ABSTRACT: base class for fields
3              
4 2     2   35536 use HTML::FormHandler::Moose;
  0            
  0            
5             use HTML::FormHandler::Field::Result;
6             use Try::Tiny;
7             use Moose::Util::TypeConstraints;
8             use HTML::FormHandler::Merge ('merge');
9             use HTML::FormHandler::Render::Util('cc_widget', 'ucc_widget');
10             use Sub::Name;
11              
12             with 'HTML::FormHandler::Traits';
13             with 'HTML::FormHandler::Validate';
14             with 'HTML::FormHandler::Widget::ApplyRole';
15             with 'HTML::FormHandler::TraitFor::Types';
16              
17             our $VERSION = '0.02';
18              
19              
20             has 'name' => ( isa => 'Str', is => 'rw', required => 1 );
21             has 'type' => ( isa => 'Str', is => 'rw', default => sub { ref shift } );
22             has 'parent' => ( is => 'rw', predicate => 'has_parent', weak_ref => 1 );
23             sub has_fields { }
24             has 'input_without_param' => (
25             is => 'rw',
26             predicate => 'has_input_without_param'
27             );
28             has 'not_nullable' => ( is => 'rw', isa => 'Bool' );
29             has 'no_value_if_empty' => ( is => 'rw', isa => 'Bool' );
30             has 'validate_when_empty' => ( is => 'rw', isa => 'Bool' );
31             has 'init_value' => ( is => 'rw', clearer => 'clear_init_value', predicate => 'has_init_value' );
32             has 'default' => ( is => 'rw' );
33             has 'default_over_obj' => ( is => 'rw', builder => 'build_default_over_obj' );
34             sub build_default_over_obj { }
35             has 'result' => (
36             isa => 'HTML::FormHandler::Field::Result',
37             is => 'ro',
38             weak_ref => 1,
39             clearer => 'clear_result',
40             predicate => 'has_result',
41             writer => '_set_result',
42             handles => [
43             '_set_input', '_clear_input', '_set_value', '_clear_value',
44             'errors', 'all_errors', '_push_errors', 'num_errors', 'has_errors',
45             'clear_errors', 'validated', 'add_warning', 'all_warnings', 'num_warnings',
46             'has_warnings', 'warnings', 'missing',
47             ],
48             );
49             has '_pin_result' => ( is => 'ro', reader => '_get_pin_result', writer => '_set_pin_result' );
50              
51             sub has_input {
52             my $self = shift;
53             return unless $self->has_result;
54             return $self->result->has_input;
55             }
56              
57             sub has_value {
58             my $self = shift;
59             return unless $self->has_result;
60             return $self->result->has_value;
61             }
62              
63             # these should normally only be called for field tests
64             sub reset_result {
65             my $self = shift;
66             $self->clear_result;
67             $self->build_result;
68             }
69             sub build_result {
70             my $self = shift;
71             my @parent = ( 'parent' => $self->parent->result )
72             if ( $self->parent && $self->parent->result );
73             my $result = HTML::FormHandler::Field::Result->new(
74             name => $self->name,
75             field_def => $self,
76             @parent
77             );
78             $self->_set_pin_result($result); # to prevent garbage collection of result
79             $self->_set_result($result);
80             }
81              
82             sub input {
83             my $self = shift;
84              
85             # allow testing fields individually by creating result if no form
86             return undef unless $self->has_result || !$self->form;
87             my $result = $self->result;
88             return $result->_set_input(@_) if @_;
89             return $result->input;
90             }
91              
92             sub value {
93             my $self = shift;
94              
95             # allow testing fields individually by creating result if no form
96             return undef unless $self->has_result || !$self->form;
97             my $result = $self->result;
98             return undef unless $result;
99             return $result->_set_value(@_) if @_;
100             return $result->value;
101             }
102             # for compatibility. deprecate and remove at some point
103             sub clear_input { shift->_clear_input }
104             sub clear_value { shift->_clear_value }
105             sub clear_data {
106             my $self = shift;
107             $self->clear_result;
108             $self->clear_active;
109             }
110             # this is a kludge to allow testing field deflation
111             sub _deflate_and_set_value {
112             my ( $self, $value ) = @_;
113             if( $self->_can_deflate ) {
114             $value = $self->_apply_deflation($value);
115             }
116             $self->_set_value($value);
117             }
118              
119             sub is_repeatable { }
120              
121             has 'fif_from_value' => ( isa => 'Str', is => 'ro' );
122              
123             sub fif {
124             my ( $self, $result ) = @_;
125              
126             return if ( $self->inactive && !$self->_active );
127             return '' if $self->password;
128             return unless $result || $self->has_result;
129             my $lresult = $result || $self->result;
130             if ( ( $self->has_result && $self->has_input && !$self->fif_from_value ) ||
131             ( $self->fif_from_value && !defined $lresult->value ) )
132             {
133             return defined $lresult->input ? $lresult->input : '';
134             }
135             if ( defined $lresult->value ) {
136             if( $self->_can_deflate ) {
137             return $self->_apply_deflation($lresult->value);
138             }
139             else {
140             return $lresult->value;
141             }
142             }
143             elsif ( defined $self->value ) {
144             # this is because checkboxes and submit buttons have their own 'value'
145             # needs to be fixed in some better way
146             return $self->value;
147             }
148             return '';
149             }
150              
151             has 'accessor' => (
152             isa => 'Str',
153             is => 'rw',
154             lazy => 1,
155             default => sub {
156             my $self = shift;
157             my $accessor = $self->name;
158             $accessor =~ s/^(.*)\.//g if ( $accessor =~ /\./ );
159             return $accessor;
160             }
161             );
162             has 'is_contains' => ( is => 'rw', isa => 'Bool' );
163             has 'temp' => ( is => 'rw' );
164              
165             sub has_flag {
166             my ( $self, $flag_name ) = @_;
167             return unless $self->can($flag_name);
168             return $self->$flag_name;
169             }
170              
171             has 'label' => (
172             isa => 'Maybe[Str]',
173             is => 'rw',
174             lazy => 1,
175             builder => 'build_label',
176             );
177             has 'do_label' => ( isa => 'Bool', is => 'rw', default => 1 );
178             has 'build_label_method' => ( is => 'rw', isa => 'CodeRef',
179             traits => ['Code'], handles => { 'build_label' => 'execute_method' },
180             default => sub { \&default_build_label },
181             );
182             sub default_build_label {
183             my $self = shift;
184             my $label = $self->name;
185             $label =~ s/_/ /g;
186             $label = ucfirst($label);
187             return $label;
188             }
189             sub loc_label {
190             my $self = shift;
191             return $self->_localize($self->label);
192             }
193             has 'wrap_label_method' => (
194             traits => ['Code'],
195             is => 'ro',
196             isa => 'CodeRef',
197             predicate => 'does_wrap_label',
198             handles => { 'wrap_label' => 'execute_method' },
199             );
200             has 'title' => ( isa => 'Str', is => 'rw' );
201             has 'style' => ( isa => 'Str', is => 'rw' );
202             has 'form' => (
203             isa => 'HTML::FormHandler',
204             is => 'rw',
205             weak_ref => 1,
206             predicate => 'has_form',
207             );
208             sub is_form { 0 }
209             has 'html_name' => (
210             isa => 'Str',
211             is => 'rw',
212             lazy => 1,
213             builder => 'build_html_name'
214             );
215              
216             sub build_html_name {
217             my $self = shift;
218             my $prefix = ( $self->form && $self->form->html_prefix ) ? $self->form->name . "." : '';
219             return $prefix . $self->full_name;
220             }
221             has 'widget' => ( isa => 'Str', is => 'rw' );
222             has 'widget_wrapper' => ( isa => 'Str', is => 'rw' );
223             has 'do_wrapper' => ( is => 'rw', default => 1 );
224             sub wrapper { shift->widget_wrapper || '' }
225             sub uwrapper { ucc_widget( shift->widget_wrapper || '' ) || 'simple' }
226             sub twrapper { shift->uwrapper . ".tt" }
227             sub uwidget { ucc_widget( shift->widget || '' ) || 'simple' }
228             sub twidget { shift->uwidget . ".tt" }
229             # for use of wrapper classes
230             has 'wrapper_tags' => (
231             isa => 'HashRef',
232             traits => ['Hash'],
233             is => 'rw',
234             builder => 'build_wrapper_tags',
235             handles => {
236             has_wrapper_tags => 'count'
237             }
238             );
239             sub build_wrapper_tags { {} }
240             has 'tags' => (
241             traits => ['Hash'],
242             isa => 'HashRef',
243             is => 'rw',
244             builder => 'build_tags',
245             handles => {
246             _get_tag => 'get',
247             set_tag => 'set',
248             has_tag => 'exists',
249             tag_exists => 'exists',
250             delete_tag => 'delete',
251             },
252             );
253             sub build_tags {{}}
254             sub merge_tags {
255             my ( $self, $new ) = @_;
256             my $old = $self->tags;
257             $self->tags( merge($new, $old) );
258             }
259             sub get_tag {
260             my ( $self, $name ) = @_;
261             return '' unless $self->tag_exists($name);
262             my $tag = $self->_get_tag($name);
263             return $self->$tag if ref $tag eq 'CODE';
264             return $tag unless $tag =~ /^%/;
265             ( my $block_name = $tag ) =~ s/^%//;
266             return $self->form->block($block_name)->render
267             if ( $self->form && $self->form->block_exists($block_name) );
268             return '';
269             }
270              
271             has 'widget_name_space' => (
272             isa => 'HFH::ArrayRefStr',
273             is => 'rw',
274             traits => ['Array'],
275             default => sub {[]},
276             coerce => 1,
277             handles => {
278             push_widget_name_space => 'push',
279             },
280             );
281              
282             sub add_widget_name_space {
283             my ( $self, @ns ) = @_;
284             @ns = @{$ns[0]}if( scalar @ns && ref $ns[0] eq 'ARRAY' );
285             $self->push_widget_name_space(@ns);
286             }
287              
288             has 'order' => ( isa => 'Int', is => 'rw', default => 0 );
289             # 'inactive' is set in the field declaration, and is static. Default status.
290             has 'inactive' => ( isa => 'Bool', is => 'rw', clearer => 'clear_inactive' );
291             # 'active' is cleared whenever the form is cleared. Ephemeral activation.
292             has '_active' => ( isa => 'Bool', is => 'rw', clearer => 'clear_active', predicate => 'has__active' );
293             sub is_active {
294             my $self = shift;
295             return ! $self->is_inactive;
296             }
297             sub is_inactive {
298             my $self = shift;
299             return (($self->inactive && !$self->_active) || (!$self->inactive && $self->has__active && $self->_active == 0 ) );
300             }
301             has 'id' => ( isa => 'Str', is => 'rw', lazy => 1, builder => 'build_id' );
302             has 'build_id_method' => ( is => 'rw', isa => 'CodeRef', traits => ['Code'],
303             default => sub { sub { shift->html_name } },
304             handles => { build_id => 'execute_method' },
305             );
306              
307             # html attributes
308             has 'password' => ( isa => 'Bool', is => 'rw' );
309             has 'disabled' => ( isa => 'Bool', is => 'rw' );
310             has 'readonly' => ( isa => 'Bool', is => 'rw' );
311             has 'tabindex' => ( is => 'rw', isa => 'Int' );
312              
313             sub html_element { 'input' }
314             has 'type_attr' => ( is => 'rw', isa => 'Str', default => 'text' );
315             has 'html5_type_attr' => ( isa => 'Str', is => 'ro', default => 'text' );
316             sub input_type {
317             my $self = shift;
318             return $self->html5_type_attr if ( $self->form && $self->form->has_flag('is_html5') );
319             return $self->type_attr;
320             }
321             # temporary methods for compatibility after name change
322             sub html_attr { shift->element_attr(@_) }
323             sub has_html_attr { shift->has_element_attr(@_) }
324             sub get_html_attr { shift->get_element_attr(@_) }
325             sub set_html_attr { shift->set_element_attr(@_) }
326              
327             {
328             # create the attributes and methods for
329             # element_attr, build_element_attr, element_class,
330             # label_attr, build_label_attr, label_class,
331             # wrapper_attr, build_wrapper_atrr, wrapper_class
332             no strict 'refs';
333             foreach my $attr ('wrapper', 'element', 'label' ) {
334             # trigger to move 'class' set via _attr to the class slot
335             my $add_meth = "add_${attr}_class";
336             my $trigger_sub = sub {
337             my ( $self, $value ) = @_;
338             if( my $class = delete $self->{"${attr}_attr"}->{class} ) {
339             $self->$add_meth($class);
340             }
341             };
342             has "${attr}_attr" => ( is => 'rw', traits => ['Hash'],
343             builder => "build_${attr}_attr",
344             handles => {
345             "has_${attr}_attr" => 'count',
346             "get_${attr}_attr" => 'get',
347             "set_${attr}_attr" => 'set',
348             "delete_${attr}_attr" => 'delete',
349             "exists_${attr}_attr" => 'exists',
350             },
351             trigger => $trigger_sub,
352             );
353             # create builders fo _attrs
354             my $attr_builder = __PACKAGE__ . "::build_${attr}_attr";
355             *$attr_builder = subname $attr_builder, sub {{}};
356             # create the 'class' slots
357             has "${attr}_class" => ( is => 'rw', isa => 'HFH::ArrayRefStr',
358             traits => ['Array'],
359             coerce => 1,
360             builder => "build_${attr}_class",
361             handles => {
362             "has_${attr}_class" => 'count',
363             "_add_${attr}_class" => 'push',
364             },
365             );
366             # create builders for classes
367             my $class_builder = __PACKAGE__ . "::build_${attr}_class";
368             *$class_builder = subname $class_builder, sub {[]};
369             # create wrapper for add_to_ to accept arrayref
370             my $add_to_class = __PACKAGE__ . "::add_${attr}_class";
371             my $_add_meth = __PACKAGE__ . "::_add_${attr}_class";
372             *$add_to_class = subname $add_to_class, sub { shift->$_add_meth((ref $_[0] eq 'ARRAY' ? @{$_[0]} : @_)); }
373             }
374             }
375              
376             # we're assuming that the only attribute we want in an element wrapper is a class
377             has 'element_wrapper_class' => (
378             is => 'rw', isa => 'HFH::ArrayRefStr',
379             traits => ['Array'],
380             coerce => 1,
381             builder => "build_element_wrapper_class",
382             handles => {
383             has_element_wrapper_class => 'count',
384             _add_element_wrapper_class => 'push',
385             },
386             );
387             sub add_element_wrapper_class { shift->_add_element_wrapper_class((ref $_[0] eq 'ARRAY' ? @{$_[0]} : @_)); }
388             sub build_element_wrapper_class { [] }
389             sub element_wrapper_attributes {
390             my ( $self, $result ) = @_;
391             $result ||= $self->result;
392             # local copy of label_attr
393             my $attr = {};
394             my $class = [@{$self->element_wrapper_class}];
395             $self->add_standard_element_wrapper_classes( $result, $class );
396             $attr->{class} = $class if @$class;
397             # call form hook
398             my $mod_attr = $self->form->html_attributes($self, 'element_wrapper', $attr, $result) if $self->form;
399             return ref($mod_attr) eq 'HASH' ? $mod_attr : $attr;
400             }
401             sub add_standard_element_wrapper_classes {
402             my ( $self, $result, $class ) = @_;
403             }
404              
405             sub attributes { shift->element_attributes(@_) }
406             sub element_attributes {
407             my ( $self, $result ) = @_;
408             $result ||= $self->result;
409             my $attr = {};
410             # handle html5 attributes
411             if ($self->form && $self->form->has_flag('is_html5')) {
412             $attr->{required} = 'required' if $self->required;
413             $attr->{min} = $self->range_start if defined $self->range_start;
414             $attr->{max} = $self->range_end if defined $self->range_end;
415             }
416             # pull in deprecated attributes for backward compatibility
417             for my $dep_attr ( 'readonly', 'disabled' ) {
418             $attr->{$dep_attr} = $dep_attr if $self->$dep_attr;
419             }
420             for my $dep_attr ( 'style', 'title', 'tabindex' ) {
421             $attr->{$dep_attr} = $self->$dep_attr if defined $self->$dep_attr;
422             }
423             $attr = {%$attr, %{$self->element_attr}};
424             my $class = [@{$self->element_class}];
425             $self->add_standard_element_classes($result, $class);
426             $attr->{class} = $class if @$class;
427             # call form hook
428             my $mod_attr = $self->form->html_attributes($self, 'element', $attr, $result) if $self->form;
429             return ref($mod_attr) eq 'HASH' ? $mod_attr : $attr;
430             }
431              
432             sub add_standard_element_classes {
433             my ( $self, $result, $class ) = @_;
434             push @$class, 'error' if $result->has_errors;
435             push @$class, 'warning' if $result->has_warnings;
436             push @$class, 'disabled' if $self->disabled;
437             }
438              
439             sub label_attributes {
440             my ( $self, $result ) = @_;
441             $result ||= $self->result;
442             # local copy of label_attr
443             my $attr = {%{$self->label_attr}};
444             my $class = [@{$self->label_class}];
445             $self->add_standard_label_classes($result, $class);
446             $attr->{class} = $class if @$class;
447             # call form hook
448             my $mod_attr = $self->form->html_attributes($self, 'label', $attr, $result) if $self->form;
449             return ref($mod_attr) eq 'HASH' ? $mod_attr : $attr;
450             }
451              
452             sub add_standard_label_classes {
453             my ( $self, $result, $class ) = @_;
454             }
455              
456             sub wrapper_attributes {
457             my ( $self, $result ) = @_;
458             $result ||= $self->result;
459             # copy wrapper
460             my $attr = {%{$self->wrapper_attr}};
461             my $class = [@{$self->wrapper_class}];
462             # add 'error' to class
463             $self->add_standard_wrapper_classes($result, $class);
464             $attr->{class} = $class if @$class;
465             # add id if compound field and id doesn't exist unless 'no_wrapper_id' tag
466             $attr->{id} = $self->id
467             if ( $self->has_flag('is_compound') && not exists $attr->{id} && ! $self->get_tag('no_wrapper_id') );
468             # call form hook
469             my $mod_attr = $self->form->html_attributes($self, 'wrapper', $attr, $result) if $self->form;
470             return ref($mod_attr) eq 'HASH' ? $mod_attr : $attr;
471             }
472              
473             sub add_standard_wrapper_classes {
474             my ( $self, $result, $class ) = @_;
475             push @$class, 'error' if ( $result->has_error_results || $result->has_errors );
476             push @$class, 'warning' if $result->has_warnings;
477             }
478              
479              
480             sub wrapper_tag {
481             my $self = shift;
482             return $self->get_tag('wrapper_tag') || 'div';
483             }
484              
485             #=====================
486             # these may be temporary
487             sub field_filename {
488             my $self = shift;
489             return 'checkbox_tag.tt' if $self->input_type eq 'checkbox';
490             return 'input_tag.tt';
491             }
492             sub label_tag {
493             my $self = shift;
494             return $self->get_tag('label_tag') || 'label';
495             }
496             #===================
497              
498             has 'writeonly' => ( isa => 'Bool', is => 'rw' );
499             has 'noupdate' => ( isa => 'Bool', is => 'rw' );
500              
501             #==============
502             sub convert_full_name {
503             my $full_name = shift;
504             $full_name =~ s/\.\d+\./_/g;
505             $full_name =~ s/\./_/g;
506             return $full_name;
507             }
508             has 'validate_method' => (
509             traits => ['Code'],
510             is => 'ro',
511             isa => 'CodeRef',
512             lazy => 1,
513             builder => 'build_validate_method',
514             handles => { '_validate' => 'execute_method' },
515             );
516             has 'set_validate' => ( isa => 'Str', is => 'ro',);
517             sub build_validate_method {
518             my $self = shift;
519             my $set_validate = $self->set_validate;
520             $set_validate ||= "validate_" . convert_full_name($self->full_name);
521             return sub { my $self = shift; $self->form->$set_validate($self); }
522             if ( $self->form && $self->form->can($set_validate) );
523             return sub { };
524             }
525              
526             has 'default_method' => (
527             traits => ['Code'],
528             is => 'ro',
529             isa => 'CodeRef',
530             writer => '_set_default_method',
531             predicate => 'has_default_method',
532             handles => { '_default' => 'execute_method' },
533             );
534             has 'set_default' => ( isa => 'Str', is => 'ro', writer => '_set_default');
535             # this is not a "true" builder, because sometimes 'default_method' is not set
536             sub build_default_method {
537             my $self = shift;
538             my $set_default = $self->set_default;
539             $set_default ||= "default_" . convert_full_name($self->full_name);
540             if ( $self->form && $self->form->can($set_default) ) {
541             $self->_set_default_method(
542             sub { my $self = shift; return $self->form->$set_default($self, $self->form->item); }
543             );
544             }
545             }
546              
547             sub get_default_value {
548             my $self = shift;
549             if ( $self->has_default_method ) {
550             return $self->_default;
551             }
552             elsif ( defined $self->default ) {
553             return $self->default;
554             }
555             return;
556             }
557             {
558             # create inflation/deflation methods
559             foreach my $type ( 'inflate_default', 'deflate_value', 'inflate', 'deflate' ) {
560             has "${type}_method" => ( is => 'ro', traits => ['Code'],
561             isa => 'CodeRef',
562             writer => "_set_${type}_method",
563             predicate => "has_${type}_method",
564             handles => {
565             $type => 'execute_method',
566             },
567             );
568             }
569             }
570              
571             has 'deflation' => (
572             is => 'rw',
573             predicate => 'has_deflation',
574             );
575             has 'trim' => (
576             is => 'rw',
577             default => sub { { transform => \&default_trim } }
578             );
579              
580             sub default_trim {
581             my $value = shift;
582             return unless defined $value;
583             my @values = ref $value eq 'ARRAY' ? @$value : ($value);
584             for (@values) {
585             next if ref $_ or !defined;
586             s/^\s+//;
587             s/\s+$//;
588             }
589             return ref $value eq 'ARRAY' ? \@values : $values[0];
590             }
591             has 'render_filter' => (
592             traits => ['Code'],
593             is => 'ro',
594             isa => 'CodeRef',
595             lazy => 1,
596             builder => 'build_render_filter',
597             handles => { html_filter => 'execute' },
598             );
599              
600             sub build_render_filter {
601             my $self = shift;
602              
603             if( $self->form && $self->form->can('render_filter') ) {
604             my $coderef = $self->form->can('render_filter');
605             return $coderef;
606             }
607             else {
608             return \&default_render_filter;
609             }
610             }
611              
612             sub default_render_filter {
613             my $string = shift;
614             return '' if (!defined $string);
615             $string =~ s/&/&/g;
616             $string =~ s/</&lt;/g;
617             $string =~ s/>/&gt;/g;
618             $string =~ s/"/&quot;/g;
619             return $string;
620             }
621              
622             has 'input_param' => ( is => 'rw', isa => 'Str' );
623              
624             has 'language_handle' => (
625             isa => duck_type( [ qw(maketext) ] ),
626             is => 'rw',
627             reader => 'get_language_handle',
628             writer => 'set_language_handle',
629             predicate => 'has_language_handle'
630             );
631              
632             sub language_handle {
633             my ( $self, $value ) = @_;
634             if( $value ) {
635             $self->set_language_handle($value);
636             return;
637             }
638             return $self->get_language_handle if( $self->has_language_handle );
639             # if language handle isn't set use form language handle if possible
640             return $self->form->language_handle if ( $self->has_form );
641             # no form, no language handle. This should only happen when
642             # testing fields.
643             my $lh;
644             if ( $ENV{LANGUAGE_HANDLE} ) {
645             if ( blessed $ENV{LANGUAGE_HANDLE} ) {
646             $lh = $ENV{LANGUAGE_HANDLE};
647             }
648             else {
649             $lh = HTML::FormHandler::I18N->get_handle( $ENV{LANGUAGE_HANDLE} );
650             }
651             }
652             else {
653             require HTML::FormHandler::I18N;
654             $lh = HTML::FormHandler::I18N->get_handle;
655             }
656             $self->set_language_handle($lh);
657             return $lh;
658             }
659              
660             has 'localize_meth' => (
661             traits => ['Code'],
662             is => 'ro',
663             isa => 'CodeRef',
664             lazy => 1,
665             builder => 'build_localize_meth',
666             handles => { '_localize' => 'execute_method' },
667             );
668              
669             sub build_localize_meth {
670             my $self = shift;
671              
672             if( $self->form && $self->form->can('localize_meth') ) {
673             my $coderef = $self->form->can('localize_meth');
674             return $coderef;
675             }
676             else {
677             return \&default_localize;
678             }
679             }
680              
681             sub default_localize {
682             my ($self, @message) = @_;
683             my $message = $self->language_handle->maketext(@message);
684             return $message;
685             }
686              
687             has 'messages' => ( is => 'rw',
688             isa => 'HashRef',
689             traits => ['Hash'],
690             default => sub {{}},
691             handles => {
692             '_get_field_message' => 'get',
693             '_has_field_message' => 'exists',
694             'set_message' => 'set',
695             },
696             );
697              
698             our $class_messages = {
699             'field_invalid' => 'field is invalid',
700             'range_too_low' => 'Value must be greater than or equal to [_1]',
701             'range_too_high' => 'Value must be less than or equal to [_1]',
702             'range_incorrect' => 'Value must be between [_1] and [_2]',
703             'wrong_value' => 'Wrong value',
704             'no_match' => '[_1] does not match',
705             'not_allowed' => '[_1] not allowed',
706             'error_occurred' => 'error occurred',
707             'required' => '[_1] field is required',
708             'unique' => 'Duplicate value for [_1]',
709             };
710              
711             sub get_class_messages {
712             my $self = shift;
713             my $messages = { %$class_messages };
714             $messages->{required} = $self->required_message
715             if $self->required_message;
716             $messages->{unique} = $self->unique_message
717             if $self->unique_message;
718             return $messages;
719             }
720              
721             sub get_message {
722             my ( $self, $msg ) = @_;
723              
724             # first look in messages set on individual field
725             return $self->_get_field_message($msg)
726             if $self->_has_field_message($msg);
727             # then look at form messages
728             return $self->form->_get_form_message($msg)
729             if $self->has_form && $self->form->_has_form_message($msg);
730             # then look for messages up through inherited field classes
731             return $self->get_class_messages->{$msg};
732             }
733             sub all_messages {
734             my $self = shift;
735             my $form_messages = $self->has_form ? $self->form->messages : {};
736             my $field_messages = $self->messages || {};
737             my $lclass_messages = $self->my_class_messages || {};
738             return {%{$lclass_messages}, %{$form_messages}, %{$field_messages}};
739             }
740              
741             sub BUILDARGS {
742             my $class = shift;
743              
744             # for backwards compatibility; these will be removed eventually
745             my @new;
746             push @new, ('element_attr', {@_}->{html_attr} )
747             if( exists {@_}->{html_attr} );
748             push @new, ('do_label', !{@_}->{no_render_label} )
749             if( exists {@_}->{no_render_label} );
750             return $class->SUPER::BUILDARGS(@_, @new);
751             }
752              
753             sub BUILD {
754             my ( $self, $params ) = @_;
755              
756             # temporary, for compatibility. move widget_tags to tags
757             $self->merge_tags($self->wrapper_tags) if $self->has_wrapper_tags;
758             # run default method builder
759             $self->build_default_method;
760             # build validate_method; needs to happen before validation
761             # in order to have the "real" repeatable field names, not the instances
762             $self->validate_method;
763             # merge form widget_name_space
764             $self->add_widget_name_space( $self->form->widget_name_space ) if $self->form;
765             # handle apply actions
766             $self->add_action( $self->trim ) if $self->trim;
767             $self->_build_apply_list;
768             $self->add_action( @{ $params->{apply} } ) if $params->{apply};
769             }
770              
771             # this is the recursive routine that is used
772             # to initialize field results if there is no initial object and no params
773             sub _result_from_fields {
774             my ( $self, $result ) = @_;
775              
776             if ( $self->disabled && $self->has_init_value ) {
777             $result->_set_value($self->init_value);
778             }
779             elsif ( my @values = $self->get_default_value ) {
780             if ( $self->has_inflate_default_method ) {
781             @values = $self->inflate_default(@values);
782             }
783             my $value = @values > 1 ? \@values : shift @values;
784             $self->init_value($value) if defined $value;
785             $result->_set_value($value) if defined $value;
786             }
787             $self->_set_result($result);
788             $result->_set_field_def($self);
789             return $result;
790             }
791              
792             sub _result_from_input {
793             my ( $self, $result, $input, $exists ) = @_;
794              
795             if ($exists) {
796             $result->_set_input($input);
797             }
798             elsif ( $self->disabled ) {
799             # This maybe should come from _result_from_object, but there's
800             # not a reliable way to get there from here. Field can handle...
801             return $self->_result_from_fields( $result );
802             }
803             elsif ( $self->has_input_without_param ) {
804             $result->_set_input( $self->input_without_param );
805             }
806             elsif ( $self->form && $self->form->use_fields_for_input_without_param ) {
807             return $self->_result_from_fields( $result );
808             }
809             $self->_set_result($result);
810             $result->_set_field_def($self);
811             return $result;
812             }
813              
814             sub _result_from_object {
815             my ( $self, $result, $value ) = @_;
816              
817             $self->_set_result($result);
818              
819             if ( $self->form ) {
820             $self->form->init_value( $self, $value );
821             }
822             else {
823             $self->init_value($value);
824             $result->_set_value($value);
825             }
826             $result->_set_value(undef) if $self->writeonly;
827             $result->_set_field_def($self);
828             return $result;
829             }
830              
831             sub full_name {
832             my $field = shift;
833              
834             my $name = $field->name;
835             my $parent_name;
836             # field should always have a parent unless it's a standalone field test
837             if ( $field->parent ) {
838             $parent_name = $field->parent->full_name;
839             }
840             return $name unless defined $parent_name && length $parent_name;
841             return $parent_name . '.' . $name;
842             }
843              
844             sub full_accessor {
845             my $field = shift;
846              
847             my $parent = $field->parent;
848             if( $field->is_contains ) {
849             return '' unless $parent;
850             return $parent->full_accessor;
851             }
852             my $accessor = $field->accessor;
853             my $parent_accessor;
854             if ( $parent ) {
855             $parent_accessor = $parent->full_accessor;
856             }
857             return $accessor unless defined $parent_accessor && length $parent_accessor;
858             return $parent_accessor . '.' . $accessor;
859             }
860              
861             sub add_error {
862             my ( $self, @message ) = @_;
863              
864             unless ( defined $message[0] ) {
865             @message = ( $class_messages->{field_invalid});
866             }
867             @message = @{$message[0]} if ref $message[0] eq 'ARRAY';
868             my $out;
869             try {
870             $out = $self->_localize(@message);
871             }
872             catch {
873             die "Error occurred localizing error message for " . $self->label . ". Check brackets. $_";
874             };
875             return $self->push_errors($out);;
876             }
877              
878             sub push_errors {
879             my $self = shift;
880             $self->_push_errors(@_);
881             if ( $self->parent ) {
882             $self->parent->propagate_error($self->result);
883             }
884             return;
885             }
886              
887             sub _apply_deflation {
888             my ( $self, $value ) = @_;
889              
890             if ( $self->has_deflation ) {
891             $value = $self->deflation->($value);
892             }
893             elsif ( $self->has_deflate_method ) {
894             $value = $self->deflate($value);
895             }
896             return $value;
897             }
898             sub _can_deflate {
899             my $self = shift;
900             return $self->has_deflation || $self->has_deflate_method;
901             }
902              
903             # use Class::MOP to clone
904             sub clone {
905             my ( $self, %params ) = @_;
906             $self->meta->clone_object( $self, %params );
907             }
908              
909             sub value_changed {
910             my ($self) = @_;
911              
912             my @cmp;
913             for ( 'init_value', 'value' ) {
914             my $val = $self->$_;
915             $val = '' unless defined $val;
916             push @cmp, join '|', sort
917             map { ref($_) && $_->isa('DateTime') ? $_->iso8601 : "$_" }
918             ref($val) eq 'ARRAY' ? @$val : $val;
919             }
920             return $cmp[0] ne $cmp[1];
921             }
922              
923             sub required_text { shift->required ? 'required' : 'optional' }
924              
925             sub input_defined {
926             my ($self) = @_;
927             return unless $self->has_input;
928             return has_some_value( $self->input );
929             }
930              
931             sub dump {
932             my $self = shift;
933              
934             require Data::Dumper;
935             warn "HFH: ----- ", $self->name, " -----\n";
936             warn "HFH: type: ", $self->type, "\n";
937             warn "HFH: required: ", ( $self->required || '0' ), "\n";
938             warn "HFH: label: ", $self->label, "\n";
939             warn "HFH: widget: ", $self->widget || '', "\n";
940             my $v = $self->value;
941             warn "HFH: value: ", Data::Dumper::Dumper($v) if $v;
942             my $iv = $self->init_value;
943             warn "HFH: init_value: ", Data::Dumper::Dumper($iv) if $iv;
944             my $i = $self->input;
945             warn "HFH: input: ", Data::Dumper::Dumper($i) if $i;
946             my $fif = $self->fif;
947             warn "HFH: fif: ", Data::Dumper::Dumper($fif) if $fif;
948              
949             if ( $self->can('options') ) {
950             my $o = $self->options;
951             warn "HFH: options: " . Data::Dumper::Dumper($o);
952             }
953             }
954              
955             sub apply_rendering_widgets {
956             my $self = shift;
957              
958             if ( $self->widget ) {
959             warn "in apply_rendering_widgets " . $self->widget . " Field\n";
960             $self->apply_widget_role( $self, $self->widget, 'Field' );
961             }
962             my $widget_wrapper = $self->widget_wrapper;
963             $widget_wrapper ||= $self->form->widget_wrapper if $self->form;
964             $widget_wrapper ||= 'Simple';
965             unless ( $widget_wrapper eq 'none' ) {
966             $self->apply_widget_role( $self, $widget_wrapper, 'Wrapper' );
967             }
968             return;
969              
970             }
971              
972             sub peek {
973             my ( $self, $indent ) = @_;
974              
975             $indent ||= '';
976             my $string = $indent . 'field: "' . $self->name . '" type: ' . $self->type . "\n";
977             if( $self->has_flag('has_contains') ) {
978             $string .= $indent . "contains: \n";
979             my $lindent = $indent . ' ';
980             foreach my $field ( $self->contains->sorted_fields ) {
981             $string .= $field->peek( $lindent );
982             }
983             }
984             if( $self->has_fields ) {
985             $string .= $indent . 'subfields of "' . $self->name . '": ' . $self->num_fields . "\n";
986             my $lindent = $indent . ' ';
987             foreach my $field ( $self->sorted_fields ) {
988             $string .= $field->peek( $lindent );
989             }
990             }
991             return $string;
992             }
993              
994             sub has_some_value {
995             my $x = shift;
996              
997             return unless defined $x;
998             return $x =~ /\S/ if !ref $x;
999             if ( ref $x eq 'ARRAY' ) {
1000             for my $elem (@$x) {
1001             return 1 if has_some_value($elem);
1002             }
1003             return 0;
1004             }
1005             if ( ref $x eq 'HASH' ) {
1006             for my $key ( keys %$x ) {
1007             return 1 if has_some_value( $x->{$key} );
1008             }
1009             return 0;
1010             }
1011             return 1 if blessed($x); # true if blessed, otherwise false
1012             return 1 if ref( $x );
1013             return;
1014             }
1015              
1016             sub apply_traits {
1017             my ($class, @traits) = @_;
1018              
1019             $class->meta->make_mutable;
1020             Moose::Util::apply_all_roles($class->meta, @traits);
1021             $class->meta->make_immutable;
1022             }
1023              
1024             __PACKAGE__->meta->make_immutable;
1025             use namespace::autoclean;
1026             1;
1027              
1028             __END__
1029              
1030             =pod
1031              
1032             =encoding UTF-8
1033              
1034             =head1 NAME
1035              
1036             HTML::FormHandler::Field - base class for fields
1037              
1038             =head1 VERSION
1039              
1040             version 0.40057
1041              
1042             =head1 SYNOPSIS
1043              
1044             Instances of Field subclasses are generally built by L<HTML::FormHandler>
1045             from 'has_field' declarations or the field_list, but they can also be constructed
1046             using new for test purposes (since there's no standard way to add a field to a form
1047             after construction).
1048              
1049             use HTML::FormHandler::Field::Text;
1050             my $field = HTML::FormHandler::Field::Text->new( name => $name, ... );
1051              
1052             In your custom field class:
1053              
1054             package MyApp::Field::MyText;
1055             use HTML::FormHandler::Moose;
1056             extends 'HTML::FormHandler::Field::Text';
1057              
1058             has 'my_attribute' => ( isa => 'Str', is => 'rw' );
1059              
1060             apply [ { transform => sub { ... } },
1061             { check => ['fighter', 'bard', 'mage' ], message => '....' }
1062             ];
1063             1;
1064              
1065             =head1 DESCRIPTION
1066              
1067             This is the base class for form fields. The 'type' of a field class
1068             is used in the FormHandler field_list or has_field to identify which field class to
1069             load from the 'field_name_space' (or directly, when prefixed with '+').
1070             If the type is not specified, it defaults to Text.
1071              
1072             See L<HTML::FormHandler::Manual::Fields> for a list of the fields and brief
1073             descriptions of their structure.
1074              
1075             =head1 ATTRIBUTES
1076              
1077             =head2 Names, types, accessor
1078              
1079             =over
1080              
1081             =item name
1082              
1083             The name of the field. Used in the HTML form. Often a db accessor.
1084             The only required attribute.
1085              
1086             =item type
1087              
1088             The class or type of the field. The 'type' of L<HTML::FormHandler::Field::Money>
1089             is 'Money'. Classes that you define yourself are prefixed with '+'.
1090              
1091             =item accessor
1092              
1093             If the name of your field is different than your database accessor, use
1094             this attribute to provide the accessor.
1095              
1096             =item full_name
1097              
1098             The name of the field with all parents:
1099              
1100             'event.start_date.month'
1101              
1102             =item full_accessor
1103              
1104             The field accessor with all parents.
1105              
1106             =item html_name
1107              
1108             The full_name plus the form name if 'html_prefix' is set.
1109              
1110             =item input_param
1111              
1112             By default we expect an input parameter based on the field name. This allows
1113             you to look for a different input parameter.
1114              
1115             =back
1116              
1117             =head2 Field data
1118              
1119             =over
1120              
1121             =item inactive, is_inactive, is_active
1122              
1123             Set the 'inactive' attribute to 1 if this field is inactive. The 'inactive' attribute
1124             that isn't set or is set to 0 will make a field 'active'.
1125             This provides a way to define fields in the form and selectively set them to inactive.
1126             There is also an '_active' attribute, for internal use to indicate that the field has
1127             been activated/inactivated on 'process' by the form's 'active'/'inactive' attributes.
1128              
1129             You can use the is_inactive and is_active methods to check whether this particular
1130             field is active.
1131              
1132             if( $form->field('foo')->is_active ) { ... }
1133              
1134             =item input
1135              
1136             The input string from the parameters passed in.
1137              
1138             =item value
1139              
1140             The value as it would come from or go into the database, after being
1141             acted on by inflations/deflations and transforms. Used to construct the
1142             C<< $form->values >> hash. Validation and constraints act on 'value'.
1143              
1144             See also L<HTML::FormHandler::Manual::InflationDeflation>.
1145              
1146             =item fif
1147              
1148             Values used to fill in the form. Read only. Use a deflation to get
1149             from 'value' to 'fif' if an inflator was used. Use 'fif_from_value'
1150             attribute if you want to use the field 'value' to fill in the form.
1151              
1152             [% form.field('title').fif %]
1153              
1154             =item init_value
1155              
1156             Initial value populated by init_from_object. You can tell if a field
1157             has changed by comparing 'init_value' and 'value'. Read only.
1158              
1159             =item input_without_param
1160              
1161             Input for this field if there is no param. Set by default for Checkbox,
1162             and Select, since an unchecked checkbox or unselected pulldown
1163             does not return a parameter.
1164              
1165             =back
1166              
1167             =head2 Form, parent
1168              
1169             =over
1170              
1171             =item form
1172              
1173             A reference to the containing form.
1174              
1175             =item parent
1176              
1177             A reference to the parent of this field. Compound fields are the
1178             parents for the fields they contain.
1179              
1180             =back
1181              
1182             =head2 Errors
1183              
1184             =over
1185              
1186             =item errors
1187              
1188             Returns the error list for the field. Also provides 'num_errors',
1189             'has_errors', 'push_errors' and 'clear_errors' from Array
1190             trait. Use 'add_error' to add an error to the array if you
1191             want to use a MakeText language handle. Default is an empty list.
1192              
1193             =item add_error
1194              
1195             Add an error to the list of errors. Error message will be localized
1196             using '_localize' method.
1197             See also L<HTML::FormHandler::TraitFor::I18N>.
1198              
1199             return $field->add_error( 'bad data' ) if $bad;
1200              
1201             =item error_fields
1202              
1203             Compound fields will have an array of errors from the subfields.
1204              
1205             =item localize_meth
1206              
1207             Set the method used to localize.
1208              
1209             =back
1210              
1211             =head2 Attributes for creating HTML
1212              
1213             The 'element_attr' hashref attribute can be used to set
1214             arbitrary HTML attributes on a field's input tag.
1215              
1216             has_field 'foo' => ( element_attr => { readonly => 1, my_attr => 'abc' } );
1217              
1218             Note that the 'id' and 'type' attributes are not set using element_attr. Use
1219             the field's 'id' attribute (or 'build_id_method') to set the id.
1220              
1221             The 'label_attr' hashref is for label attributes, and the 'wrapper_attr'
1222             is for attributes on the wrapping element (a 'div' for the standard 'simple'
1223             wrapper).
1224              
1225             A 'javascript' key in one of the '_attr' hashes will be inserted into the
1226             element as-is.
1227              
1228             The following are used in rendering HTML, but are handled specially.
1229              
1230             label - Text label for this field. Defaults to ucfirst field name.
1231             build_label_method - coderef for constructing the label
1232             wrap_label_method - coderef for constructing a wrapped label
1233             id - Useful for javascript (default is html_name. to prefix with
1234             form name, use 'html_prefix' in your form)
1235             build_id_method - coderef for constructing the id
1236             render_filter - Coderef for filtering fields before rendering. By default
1237             changes >, <, &, " to the html entities
1238             disabled - Boolean to set field disabled
1239              
1240             The order attribute may be used to set the order in which fields are rendered.
1241              
1242             order - Used for sorting errors and fields. Built automatically,
1243             but may also be explicitly set
1244              
1245             The following are discouraged. Use 'element_attr', 'label_attr', and 'wrapper_attr'
1246             instead.
1247              
1248             title - instead use element_attr => { title => '...' }
1249             style - instead use element_attr => { style => '...' }
1250             tabindex - instead use element_attr => { tabindex => 1 }
1251             readonly - instead use element_attr => { readonly => 'readonly' }
1252              
1253             Rendering of the various HTML attributes is done by calling the 'process_attrs'
1254             function (from HTML::FormHandler::Render::Util) and passing in a method that
1255             adds in error classes, provides backward compatibility with the deprecated
1256             attributes, etc.
1257              
1258             attribute hashref class attribute wrapping method
1259             ================= ================= ================
1260             element_attr element_class element_attributes
1261             label_attr label_class label_attributes
1262             wrapper_attr wrapper_class wrapper_attributes
1263             element_wrapper_class element_wrapper_attributes
1264              
1265             ('element_wrapper' is for an inner div around the input element, not
1266             including the label. Used for Bootstrap3 rendering, but also available
1267             in the Simple wrapper.)
1268             The slots for the class attributes are arrayrefs; they will coerce a
1269             string into an arrayref.
1270             In addition, these 'wrapping methods' call a hook method in the form class,
1271             'html_attributes', which you can use to customize and localize the various
1272             attributes. (Field types: 'element', 'wrapper', 'label')
1273              
1274             sub html_attributes {
1275             my ( $self, $field, $type, $attr ) = @_;
1276             $attr->{class} = 'label' if $type eq 'label';
1277             return $attr;
1278             }
1279              
1280             The 'process_attrs' function will also handle an array of strings, such as for the
1281             'class' attribute.
1282              
1283             =head2 tags
1284              
1285             A hashref containing flags and strings for use in the rendering code.
1286             The value of a tag can be a string, a coderef (accessed as a method on the
1287             field) or a block specified with a percent followed by the blockname
1288             ('%blockname').
1289              
1290             Retrieve a tag with 'get_tag'. It returns a '' if the tag doesn't exist.
1291              
1292             This attribute used to be named 'widget_tags', which is deprecated.
1293              
1294             =head2 html5_type_attr [string]
1295              
1296             This string is used when rendering an input element as the value for the type attribute.
1297             It is used when the form has the is_html5 flag on.
1298              
1299             =head2 widget
1300              
1301             The 'widget' attribute is used in rendering, so if you are
1302             not using FormHandler's rendering facility, you don't need this
1303             attribute. It is used in generating HTML, in templates and the
1304             rendering roles. Fields of different type can use the same widget.
1305              
1306             This attribute is set in the field classes, or in the fields
1307             defined in the form. If you want a new widget type, create a
1308             widget role, such as MyApp::Form::Widget::Field::MyWidget. Provide
1309             the name space in the 'widget_name_space' attribute, and set
1310             the 'widget' of your field to the package name after the
1311             Field/Form/Wrapper:
1312              
1313             has_field 'my_field' => ( widget => 'MyWidget' );
1314              
1315             If you are using a template based rendering system you will want
1316             to create a widget template.
1317             (see L<HTML::FormHandler::Manual::Templates>)
1318              
1319             Widget types for some of the provided field classes:
1320              
1321             Widget : Field classes
1322             -----------------------:---------------------------------
1323             Text : Text, Integer
1324             Checkbox : Checkbox, Boolean
1325             RadioGroup : Select, Multiple, IntRange (etc)
1326             Select : Select, Multiple, IntRange (etc)
1327             CheckboxGroup : Multiple select
1328             TextArea : TextArea
1329             Compound : Compound, Repeatable, DateTime
1330             Password : Password
1331             Hidden : Hidden
1332             Submit : Submit
1333             Reset : Reset
1334             NoRender :
1335             Upload : Upload
1336              
1337             Widget roles are automatically applied to field classes
1338             unless they already have a 'render' method, and if the
1339             'no_widgets' flag in the form is not set.
1340              
1341             You can create your own widget roles and specify the namespace
1342             in 'widget_name_space'. In the form:
1343              
1344             has '+widget_name_space' => ( default => sub { ['MyApp::Widget'] } );
1345              
1346             If you want to use a fully specified role name for a widget, you
1347             can prefix it with a '+':
1348              
1349             widget => '+MyApp::Widget::SomeWidget'
1350              
1351             For more about widgets, see L<HTML::FormHandler::Manual::Rendering>.
1352              
1353             =head2 Flags
1354              
1355             password - prevents the entered value from being displayed in the form
1356             writeonly - The initial value is not taken from the database
1357             noupdate - Do not update this field in the database (does not appear in $form->value)
1358              
1359             =head2 Defaults
1360              
1361             See also the documentation on L<HTML::FormHandler::Manual::Intro/Defaults>.
1362              
1363             =over
1364              
1365             =item default_method, set_default
1366              
1367             Supply a coderef (which will be a method on the field) with 'default_method'
1368             or the name of a form method with 'set_default' (which will be a method on
1369             the form). If not specified and a form method with a name of
1370             C<< default_<field_name> >> exists, it will be used.
1371              
1372             =item default
1373              
1374             Provide an initial value just like the 'set_default' method, except in the field
1375             declaration:
1376              
1377             has_field 'bax' => ( default => 'Default bax' );
1378              
1379             FormHandler has flipped back and forth a couple of times about whether a default
1380             specified in the has_field definition should override values provided in an
1381             initial item or init_object. Sometimes people want one behavior, and sometimes
1382             the other. Now 'default' does *not* override.
1383              
1384             If you pass in a model object with C<< item => $row >> or an initial object
1385             with C<< init_object => {....} >> the values in that object will be used instead
1386             of values provided in the field definition with 'default' or 'default_fieldname'.
1387             If you want defaults that override or supplement the item/init_object, you can use the form
1388             flags 'use_defaults_over_obj', 'use_init_obj_over_item', and
1389             'use_init_obj_when_no_accessor_in_item'.
1390              
1391             You could also put your defaults into your row or init_object instead.
1392              
1393             =item default_over_obj
1394              
1395             This is deprecated; look into using 'use_defaults_over_obj' or 'use_init_obj_over_item'
1396             flags instead. They allow using the standard 'default' attribute.
1397              
1398             Allows setting defaults which will override values provided with an item/init_object.
1399             (And only those. Will not be used for defaults without an item/init_object.)
1400              
1401             has_field 'quux' => ( default_over_obj => 'default quux' );
1402              
1403             At this time there is no equivalent of 'set_default', but the type of the attribute
1404             is not defined so you can provide default values in a variety of other ways,
1405             including providing a trait which does 'build_default_over_obj'. For examples,
1406             see tests in the distribution.
1407              
1408             =back
1409              
1410             =head1 Constraints and Validations
1411              
1412             See also L<HTML::FormHandler::Manual::Validation>.
1413              
1414             =head2 Constraints set in attributes
1415              
1416             =over
1417              
1418             =item required
1419              
1420             Flag indicating whether this field must have a value
1421              
1422             =item unique
1423              
1424             For DB field - check for uniqueness. Action is performed by
1425             the DB model.
1426              
1427             =item messages
1428              
1429             messages => { required => '...', unique => '...' }
1430              
1431             Set messages created by FormHandler by setting in the 'messages'
1432             hashref. Some field subclasses have additional settable messages.
1433              
1434             required: Error message text added to errors if required field is not present.
1435             The default is "Field <field label> is required".
1436              
1437             =item range_start
1438              
1439             =item range_end
1440              
1441             Field values are validated against the specified range if one
1442             or both of range_start and range_end are set and the field
1443             does not have 'options'.
1444              
1445             The IntRange field uses this range to create a select list
1446             with a range of integers.
1447              
1448             In a FormHandler field_list:
1449              
1450             age => {
1451             type => 'Integer',
1452             range_start => 18,
1453             range_end => 120,
1454             }
1455              
1456             =item not_nullable
1457              
1458             Fields that contain 'empty' values such as '' are changed to undef in the validation process.
1459             If this flag is set, the value is not changed to undef. If your database column requires
1460             an empty string instead of a null value (such as a NOT NULL column), set this attribute.
1461              
1462             has_field 'description' => (
1463             type => 'TextArea',
1464             not_nullable => 1,
1465             );
1466              
1467             This attribute is also used when you want an empty array to stay an empty array and not
1468             be set to undef.
1469              
1470             It's also used when you have a compound field and you want the 'value' returned
1471             to contain subfields with undef, instead of the whole field to be undef.
1472              
1473             =back
1474              
1475             =head2 apply
1476              
1477             Use the 'apply' keyword to specify an ArrayRef of constraints and coercions to
1478             be executed on the field at validate_field time.
1479              
1480             has_field 'test' => (
1481             apply => [ 'MooseType',
1482             { check => sub {...}, message => { } },
1483             { transform => sub { ... lc(shift) ... } }
1484             ],
1485             );
1486              
1487             See more documentation in L<HTML::FormHandler::Manual::Validation>.
1488              
1489             =head2 trim
1490              
1491             An action to trim the field. By default
1492             this contains a transform to strip beginning and trailing spaces.
1493             Set this attribute to null to skip trimming, or supply a different
1494             transform.
1495              
1496             trim => { transform => sub {
1497             my $string = shift;
1498             $string =~ s/^\s+//;
1499             $string =~ s/\s+$//;
1500             return $string;
1501             } }
1502             trim => { type => MyTypeConstraint }
1503              
1504             Trimming is performed before any other defined actions.
1505              
1506             =head2 Inflation/deflation
1507              
1508             There are a number of methods to provide finely tuned inflation and deflation:
1509              
1510             =over 4
1511              
1512             =item inflate_method
1513              
1514             Inflate to a data format desired for validation.
1515              
1516             =item deflate_method
1517              
1518             Deflate to a string format for presenting in HTML.
1519              
1520             =item inflate_default_method
1521              
1522             Modify the 'default' provided by an 'item' or 'init_object'.
1523              
1524             =item deflate_value_method
1525              
1526             Modify the value returned by C<< $form->value >>.
1527              
1528             =item deflation
1529              
1530             Another way of providing a deflation method.
1531              
1532             =item transform
1533              
1534             Another way of providing an inflation method.
1535              
1536             =back
1537              
1538             Normally if you have a deflation, you will need a matching inflation.
1539             There are two different flavors of inflation/deflation: one for inflating values
1540             to a format needed for validation and deflating for output, the other for
1541             inflating the initial provided values (usually from a database row) and deflating
1542             them for the 'values' returned.
1543              
1544             See L<HTML::FormHandler::Manual::InflationDeflation>.
1545              
1546             =head1 Processing and validating the field
1547              
1548             =head2 validate_field
1549              
1550             This is the base class validation routine. Most users will not
1551             do anything with this. It might be useful for method modifiers,
1552             if you want code that executed before or after the validation
1553             process.
1554              
1555             =head2 validate
1556              
1557             This field method can be used in addition to or instead of 'apply' actions
1558             in custom field classes.
1559             It should validate the field data and set error messages on
1560             errors with C<< $field->add_error >>.
1561              
1562             sub validate {
1563             my $field = shift;
1564             my $value = $field->value;
1565             return $field->add_error( ... ) if ( ... );
1566             }
1567              
1568             =head2 validate_method, set_validate
1569              
1570             Supply a coderef (which will be a method on the field) with 'validate_method'
1571             or the name of a form method with 'set_validate' (which will be a method on
1572             the form). If not specified and a form method with a name of
1573             C<< validate_<field_name> >> exists, it will be used.
1574              
1575             Periods in field names will be replaced by underscores, so that the field
1576             'addresses.city' will use the 'validate_addresses_city' method for validation.
1577              
1578             has_field 'my_foo' => ( validate_method => \&my_foo_validation );
1579             sub my_foo_validation { ... }
1580             has_field 'title' => ( isa => 'Str', set_validate => 'check_title' );
1581              
1582             =head1 AUTHOR
1583              
1584             FormHandler Contributors - see HTML::FormHandler
1585              
1586             =head1 COPYRIGHT AND LICENSE
1587              
1588             This software is copyright (c) 2014 by Gerda Shank.
1589              
1590             This is free software; you can redistribute it and/or modify it under
1591             the same terms as the Perl 5 programming language system itself.
1592              
1593             =cut