File Coverage

blib/lib/HTML/FormBuilder.pm
Criterion Covered Total %
statement 177 188 94.1
branch 62 78 79.4
condition 23 37 62.1
subroutine 21 22 95.4
pod 3 9 33.3
total 286 334 85.6


line stmt bran cond sub pod time code
1             package HTML::FormBuilder;
2              
3 7     7   161150 use strict;
  7         17  
  7         180  
4 7     7   35 use warnings;
  7         14  
  7         167  
5 7     7   137 use 5.008_005;
  7         26  
6             our $VERSION = '0.11';
7              
8 7     7   42 use Carp;
  7         11  
  7         497  
9 7     7   3922 use HTML::FormBuilder::FieldSet;
  7         21  
  7         300  
10 7     7   5985 use String::Random ();
  7         29863  
  7         164  
11 7     7   46 use Moo;
  7         11  
  7         46  
12 7     7   2060 use namespace::clean;
  7         12  
  7         48  
13 7     7   7031 use HTML::Entities;
  7         35864  
  7         18409  
14             extends qw(HTML::FormBuilder::Base);
15              
16             has data => (
17             is => 'ro',
18             isa => sub {
19             my $data = shift;
20             croak('data should be a hashref') unless ref($data) eq 'HASH';
21             croak("Form must be given an id when instantiating a HTML::FormBuilder->new object in $0.") if !defined $data->{'id'};
22             },
23             default => sub {
24             {};
25             },
26             );
27              
28             has fieldsets => (
29             is => 'rw',
30             isa => sub {
31             my $fieldsets = shift;
32             return 1 unless $fieldsets;
33             croak('fieldsets should be an arrayref')
34             unless ref($fieldsets) eq 'ARRAY';
35             },
36             default => sub {
37             [];
38             },
39             );
40              
41             has after_form => (
42             is => 'rw',
43             isa => sub {
44             return !ref($_[0]);
45             });
46              
47             has csrftoken => (is => 'ro');
48              
49             sub BUILDARGS {
50 27     27 0 31110 my ($class, @args) = @_;
51 27 50       197 my %args = (@args % 2) ? %{$args[0]} : @args;
  0         0  
52              
53             # set default class
54 27 100       85 if ($args{classes}) {
55 16         24 $args{classes} = {%{$HTML::FormBuilder::Base::CLASSES}, %{$args{classes}}};
  16         79  
  16         211  
56             } else {
57 11         16 $args{classes} = {%{$HTML::FormBuilder::Base::CLASSES}};
  11         136  
58             }
59              
60 27 100 100     209 if (($args{csrftoken} // '') eq '1') {
61 2         16 $args{csrftoken} = String::Random::random_regex('[a-zA-Z0-9]{16}');
62             }
63              
64 27   100     755 $args{data}{method} ||= 'get';
65 27 100       97 $args{data}{method} = 'get' if $args{data}{method} ne 'post';
66 27         625 return \%args;
67             }
68              
69             #####################################################################
70             # Usage : Add a new fieldset to the form
71             # Purpose : Allow the form object to carry more than 1 fieldsets
72             # Returns : Fieldset object
73             # Parameters : Hash reference with keys in <fieldsets> supported attributes
74             # Comments : Fieldset works like a table, which allow one form to
75             # have more than 1 fieldset. Each Fieldset has its own
76             # input fields.
77             # See Also :
78             #####################################################################
79             sub add_fieldset {
80 26     26 1 3429 my $self = shift;
81 26         38 my $_args = shift;
82              
83             #check if the $args is a ref HASH
84 26 50       84 croak("Parameters must in HASH reference in $0.")
85             if (ref $_args ne 'HASH');
86              
87 26         586 my $fieldset = HTML::FormBuilder::FieldSet->new(
88             data => $_args,
89             classes => $self->classes,
90             localize => $self->localize
91             );
92              
93 26         245 push @{$self->{fieldsets}}, $fieldset;
  26         66  
94              
95 26         70 return $fieldset;
96             }
97              
98             #####################################################################
99             # Usage : Add a new input fields to the fieldset
100             # Purpose : Check is the fieldset is created, and if is created
101             # add the input field into the fieldset
102             # Returns :
103             # Parameters : Hash reference with keys
104             # 'label' => $ref_hash
105             # 'input' => $ref_hash
106             # 'error' => $ref_hash
107             # 'comment' => $ref_hash
108             # Comments : check pod below to understand how to create different input fields
109             # See Also :
110             #####################################################################
111             sub add_field {
112 2     2 1 875 my $self = shift;
113 2         4 my $fieldset_index = shift;
114 2         4 my $_args = shift;
115              
116             #check if the fieldset_index is number
117 2 100       31 croak("The fieldset_index should be a number")
118             unless ($fieldset_index =~ /^\d+$/);
119              
120             #check if the fieldset array is already created
121             croak("The fieldset does not exist in $0. form_id[$self->{data}{'id'}]")
122 1 50       2 if ($fieldset_index > $#{$self->{fieldsets}});
  1         17  
123              
124 0         0 my $fieldset = $self->{fieldsets}[$fieldset_index];
125 0         0 return $fieldset->add_field($_args);
126              
127             }
128              
129             #####################################################################
130             # Usage : generate the form
131             # Purpose : check and parse the parameters and generate the form
132             # properly
133             # Returns : form HTML
134             # Parameters : Fieldset index that would like to print, null to print all
135             # Comments :
136             # See Also :
137             # TODO : seems the parameter fieldset index useless.
138             #####################################################################
139             sub build {
140 16     16 1 1686 my $self = shift;
141 16         21 my $print_fieldset_index = shift;
142              
143             # build the fieldset, if $print_fieldset_index is specifed then
144             # we only generate that praticular fieldset with that index
145 16         27 my @fieldsets;
146 16 50       36 if (defined $print_fieldset_index) {
147 0         0 push @fieldsets, $self->{'fieldsets'}[$print_fieldset_index];
148             } else {
149 16         23 @fieldsets = @{$self->{'fieldsets'}};
  16         46  
150             }
151              
152 16         54 my %grouped_fieldset;
153              
154             # build the form fieldset
155 16         39 foreach my $fieldset (@fieldsets) {
156 18         63 my ($fieldset_group, $fieldset_html) = $fieldset->build();
157 18         32 push @{$grouped_fieldset{$fieldset_group}}, $fieldset_html;
  18         71  
158             }
159              
160 16         29 my $fieldsets_html = '';
161 16         51 foreach my $fieldset_group (sort keys %grouped_fieldset) {
162 14 100       39 if ($fieldset_group ne 'no-group') {
163 1         4 $fieldsets_html .= qq[<div id="$fieldset_group" class="$self->{classes}{fieldset_group}">];
164             }
165              
166 14         18 foreach my $fieldset_html (@{$grouped_fieldset{$fieldset_group}}) {
  14         31  
167 18         61 $fieldsets_html .= $fieldset_html;
168             }
169              
170 14 100       47 if ($fieldset_group ne 'no-group') {
171 1         2 $fieldsets_html .= '</div>';
172             }
173             }
174              
175 16 100       78 if ($self->csrftoken) {
176 2         9 $fieldsets_html .= sprintf qq(<input type="hidden" name="csrftoken" value="%s"/>), $self->csrftoken;
177             }
178              
179 16         82 my $html = $self->_build_element_and_attributes('form', $self->{data}, $fieldsets_html);
180              
181 16 100       303 if ($self->after_form) {
182 1         26 $html .= $self->after_form;
183             }
184              
185 16         2414 return $html;
186             }
187              
188             #
189             # This builds a bare-bone version of the form with all inputs hidden and only
190             # displays a confirmation button. It can be used for when we'd like to ask
191             # the Client to confirm what has been entered before processing.
192             #
193             # This output currently only outputs text or hidden fields, and ignores the
194             # rest. Extra functionality would need to be added to handle any type of form.
195             #
196             sub build_confirmation_button_with_all_inputs_hidden {
197 3     3 0 905 my $self = shift;
198 3         7 my @inputs;
199              
200             # get all inputs that are to be output as hidden
201 3         6 foreach my $fieldset (@{$self->{'fieldsets'}}) {
  3         10  
202             INPUT:
203 2         6 foreach my $input_field (@{$fieldset->{'fields'}}) {
  2         7  
204 2         5 my $data = $input_field->{data};
205 2 50       10 next INPUT if (not defined $data->{'input'});
206              
207 2         4 push @inputs, @{$data->{'input'}};
  2         11  
208              
209             }
210             }
211              
212 3         8 my $html = '';
213              
214 3         10 foreach my $input (@inputs) {
215 2 50 33     19 next if ($input->{'type'} and $input->{'type'} eq 'submit');
216 2   50     9 my $n = $input->{'name'} || '';
217 2   50     12 my $val = $self->get_field_value($input->{'id'}) || '';
218 2         12 $html .= qq{<input type="hidden" name="$n" value="$val"/>};
219             }
220              
221 3 100       15 if ($self->csrftoken) {
222 1         6 $html .= sprintf qq(<input type="hidden" name="csrftoken" value="%s"/>), $self->csrftoken;
223             }
224              
225 3         8 $html .= '<input type="hidden" name="process" value="1"/>';
226             $html .= _link_button({
227             value => $self->_localize('Back'),
228             class => $self->{classes}{backbutton},
229 3         33 href => 'javascript:history.go(-1)',
230             });
231 3         16 $html .= ' <span class="button"><button id="submit" class="button" type="submit">' . $self->_localize('Confirm') . '</button></span>';
232 3         19 $html = $self->_build_element_and_attributes('form', $self->{data}, $html);
233              
234 3         15 return $html;
235             }
236              
237             ################################################################################
238             # Usage : $form_obj->set_field_value('input_element_id', 'foo');
239             # Purpose : Set input value based on input element id
240             # Returns : none
241             # Parameters : $field_id: Input element ID
242             # $field_value: Value (text)
243             # Comments : Public
244             # See Also : get_field_value
245             ################################################################################
246             sub set_field_value {
247 62     62 0 189 my $self = shift;
248 62         79 my $field_id = shift;
249 62         74 my $field_value = shift;
250 62 50       135 return unless $field_id;
251              
252 62         130 my $input_field = $self->_get_input_field($field_id);
253 62 100       140 return unless $input_field;
254              
255 60         81 my $data = $input_field->{data};
256 60         86 my $inputs = $data->{input};
257              
258             map {
259 86 100 66     625 if ($_->{'id'} and $_->{'id'} eq $field_id) {
260 60 100       78 if (eval { $_->can('value') }) {
  60 100       495  
    50          
261             # for select box
262 13         42 $_->value($field_value);
263             } elsif ($_->{'type'} =~ /(?:text|textarea|password|hidden|file)/i) {
264 36   50     144 $_->{'value'} = HTML::Entities::encode_entities($field_value // '');
265             } elsif ($_->{'type'} eq 'checkbox') {
266             # if value not set during $fieldset->add_field(), default to browser default value for checkbox: 'on'
267 11   50     107 my $checkbox_value = $_->{'value'} // 'on';
268 11 50       86 $_->{'checked'} = 'checked' if ($field_value eq $checkbox_value);
269             }
270             }
271 60         71 } @{$inputs};
  60         105  
272 60         605 return;
273             }
274              
275             ################################################################################
276             # Usage : $form_obj->get_field_value('input_element_id');
277             # Purpose : Get input value based on input element id
278             # Returns : text (Input value) / undef
279             # Parameters : $field_id: Input element ID
280             # Comments : Public
281             # See Also : set_field_value
282             ################################################################################
283             sub get_field_value {
284 88     88 0 486 my $self = shift;
285 88         114 my $field_id = shift;
286              
287 88         175 my $input_field = $self->_get_input_field($field_id);
288 88 100       245 return unless $input_field;
289              
290 86         131 my $inputs = $input_field->{data}{input};
291 86         127 foreach my $input (@$inputs) {
292 103 100 66     464 if ($input->{'id'} and $input->{'id'} eq $field_id) {
293 86 100       103 if (eval { $input->can('value') }) {
  86         502  
294 13         41 return $input->value;
295             }
296 73 50       179 return unless $input->{type};
297              
298 73 100 33     352 if ($input->{type} =~ /(?:text|textarea|password|hidden|file)/i) {
    100 66        
299 58   50     509 return HTML::Entities::decode_entities($input->{value} // '');
300             } elsif ($input->{type} eq 'checkbox' && $input->{checked} && $input->{checked} eq 'checked') {
301             # if value not set during $fieldset->add_field(), default to browser default value for checkbox: 'on'
302 11   50     61 return ($input->{value} // 'on');
303             }
304             }
305             }
306 4         20 return;
307             }
308              
309             ################################################################################
310             # Usage : 1. $form_obj->set_field_error_message('input_element_id', 'some error');
311             # 2. $form_obj->set_field_error_message('error_element_id', 'some error');
312             # Purpose : Set error message based on input element id or error element id
313             # Returns : none
314             # Parameters : $field_id: Field ID (input or error)
315             # $error_msg: Error message text
316             # Comments : Public
317             # See Also : get_field_error_message
318             ################################################################################
319             sub set_field_error_message {
320 12     12 0 16 my $self = shift;
321 12         17 my $field_id = shift;
322 12         21 my $error_msg = shift;
323              
324 12         20 my $input_field = $self->_get_input_field($field_id);
325 12 100       31 if ($input_field) {
326 11         24 $input_field->{data}{'error'}{'text'} = $error_msg;
327 11         25 return;
328             }
329              
330 1         4 my $error_field = $self->_get_error_field($field_id);
331 1 50       4 if ($error_field) {
332 1         2 $error_field->{data}{'error'}{'text'} = $error_msg;
333 1         3 return;
334             }
335 0         0 return;
336             }
337              
338             ################################################################################
339             # Usage : 1. $form_obj->get_field_error_message('input_element_id');
340             # 2. $form_obj->get_field_error_message('error_element_id');
341             # Purpose : Get error message based on input element id or error element id
342             # Returns : text (Error message)
343             # Parameters : $field_id: Field ID (input or error)
344             # Comments : Public
345             # See Also : set_field_error_message
346             ################################################################################
347             sub get_field_error_message {
348 8     8 0 427 my $self = shift;
349 8         11 my $field_id = shift;
350              
351 8         19 my $input_field = $self->_get_input_field($field_id);
352 8 100       46 return $input_field->{data}{'error'}{'text'} if $input_field;
353              
354 1         4 my $error_field = $self->_get_error_field($field_id);
355 1 50       6 return $error_field->{data}{'error'}{'text'} if $error_field;
356              
357 0         0 return;
358             }
359              
360             #####################################################################
361             # Usage : $self->_get_input_field('amount');
362             # Purpose : Get the element based on input field id
363             # Returns : Element contains input field
364             # Parameters : $field_id: Field ID
365             # Comments : Private
366             # See Also :
367             #####################################################################
368             sub _get_input_field {
369 170     170   211 my $self = shift;
370 170         214 my $field_id = shift;
371              
372 170 100       329 return unless $field_id;
373 169         195 foreach my $fieldset (@{$self->{'fieldsets'}}) {
  169         363  
374 169         190 foreach my $input_field (@{$fieldset->{'fields'}}) {
  169         302  
375 757         1066 my $inputs = $input_field->{data}{input};
376 757         1125 foreach my $sub_input_field (@$inputs) {
377 689 100 66     3152 if ( $sub_input_field->{id}
378             and $sub_input_field->{id} eq $field_id)
379             {
380 164         357 return $input_field;
381             }
382             }
383             }
384             }
385              
386 5         13 return;
387             }
388              
389             #####################################################################
390             # Usage : $self->_get_error_field('error_amount');
391             # Purpose : Get the element based on error field id
392             # Returns : Element contains error field
393             # Parameters : $error_id: Error ID
394             # Comments : Private
395             # See Also :
396             #####################################################################
397             sub _get_error_field {
398 2     2   3 my $self = shift;
399 2         3 my $error_id = shift;
400              
401 2 50       6 return unless $error_id;
402              
403             #build the form fieldset
404 2         3 foreach my $fieldset (@{$self->{'fieldsets'}}) {
  2         4  
405 2         3 foreach my $input_field (@{$fieldset->{'fields'}}) {
  2         3  
406 16 100 100     70 if ( $input_field->{data}{error}{id}
407             and $input_field->{data}{error}{id} eq $error_id)
408             {
409 2         6 return $input_field;
410             }
411             }
412             }
413 0         0 return;
414             }
415              
416             #####################################################################
417             # Usage : $self->_link_button({value => 'back', class => 'backbutton', href => '})
418             # Purpose : create link button html
419             # Returns : HTML
420             # Parameters : {value, class, href}
421             # Comments :
422             # See Also :
423             #####################################################################
424             sub _link_button {
425 3     3   16 my $args = shift;
426              
427 3 50       16 my $myclass = $args->{'class'} ? 'button ' . $args->{'class'} : 'button';
428              
429 3 50       12 my $myid = $args->{'id'} ? 'id="' . $args->{'id'} . '"' : '';
430 3 50       14 my $myspanid = $args->{'id'} ? 'id="span_' . $args->{'id'} . '"' : '';
431              
432 3         26 return qq{<a class="$myclass" href="$args->{href}" $myid><span class="$myclass" $myspanid>$args->{value}</span></a>};
433             }
434              
435             #####################################################################
436             # Usage : $self->_wrap_fieldset($fieldset_html)
437             # Purpose : wrap fieldset html by template
438             # Returns : HTML
439             # Comments :
440             # See Also :
441             #####################################################################
442             sub _wrap_fieldset {
443 0     0     my ($self, $fieldset_html) = @_;
444 0           my $output = '';
445 0           my $fieldset_template = <<EOF;
446             <div class="rbox form">
447             <div class="rbox-wrap">
448             $fieldset_html
449             <span class="tl">&nbsp;</span><span class="tr">&nbsp;</span><span class="bl">&nbsp;</span><span class="br">&nbsp;</span>
450             </div>
451             </div>
452             EOF
453              
454 0           return $fieldset_template;
455             }
456              
457             1;
458              
459             =head1 NAME
460              
461             HTML::FormBuilder - A Multi-part HTML form
462              
463             =head1 SYNOPSIS
464              
465             #define a form
466             my $form = HTML::FormBuilder->new(
467             data =>{id => 'formid',
468             class => 'formclass'},
469             classes => {row => 'rowdev'})
470              
471             #create fieldset
472             my $fieldset = $form->add_fieldset({id => 'fieldset1});
473              
474             #add field
475             $fieldset->add_field({input => {name => 'name', type => 'text', value => 'Join'}});
476              
477             #set field value
478             $form->set_field_value('name', 'Omid');
479              
480             #output the form
481             print $form->build;
482              
483             =head1 DESCRIPTION
484              
485             Object-oriented module for displaying an HTML form.
486              
487             =head2 Overview of Form's HTML structure
488              
489             The root of the structure is the <form> element and follow by multiple <fieldset> elements.
490              
491             In each <fieldset>, you can create rows which contain label, different input types, error message and comment <p> element.
492              
493             Please refer to L</"A full sample result">
494              
495             =head1 Attributes
496              
497             =head2 data
498              
499             The form attributes. It should be a hashref.
500              
501             =head2 classes
502              
503             The form classes. It should be a hashref. You can customize the form's layout by the classes.
504             The class names used are:
505              
506             fieldset_group
507             no_stack_field_parent
508             row_padding
509             fieldset_footer
510             comment
511             row
512             extra_tooltip_container
513             backbutton
514             required_asterisk
515             inputtrailing
516             label_column
517             input_column
518             hide_mobile
519              
520             =head2 localize
521              
522             The subroutine ref which can be called when translate something like 'Confirm'. The default value is no translating.
523              
524             =head2 fieldsets
525              
526             The fieldsets the form have.
527              
528             =head1 Methods
529              
530             =head2 new
531              
532             my $form = HTML::FormBuilder->new(
533             data =>{id => 'formid',
534             class => 'formclass'},
535             classes => {row => 'rowdev'})
536              
537             The id is required for the form.
538              
539             =head2 add_fieldset
540              
541             my $fieldset = $form->add_fieldset({id => 'fieldset1});
542              
543             the parameter is the fieldset attributes.
544             It will return the fielset object.
545              
546             =head2 add_field
547              
548             $form->add_field(0, {input => {name => 'name', type => 'text', value => 'Join'}});
549              
550             The parameter is the fieldset index to which you want to add the field and the field attributes.
551              
552             =head2 build
553              
554             print $form->build;
555              
556             the data in the $form will be changed when build the form. So you cannot get the same result if you call build twice.
557              
558             =head1 Cookbook
559              
560             =head2 a full sample
561              
562             # Before create a form, create a classes hash for the form
563             my $classes = {comment => 'comment', 'input_column' => 'column'};
564             # And maybe you need a localize function to translate something
565             my $localize = sub {i18n(shift)};
566              
567             # First, create the Form object. The keys in the HASH reference is the attributes of the form
568             $form_attributes => {'id' => 'id_of_the_form',
569             'name' => 'name_of_the_form',
570             'method' => 'post', # or get
571             'action' => 'page_to_submit',
572             'header' => 'My Form',
573             'localize' => $localize,
574             'classes' => $classes,
575             }; #header of the form
576             my $form = HTML::FormBuilder->new(data => $form_attributes, classes => $classes, localize => $localize);
577              
578             #Then create fieldset, the form is allow to have more than 1 fieldset
579             #The keys in the HASH reference is the attributes of the fieldset
580              
581             $fieldset_attributes => {'id' => 'id_of_the_fieldset',
582             'name' => 'name_of_the_fieldset',
583             'class' => 'myclass',
584             'header' => 'User details', #header of the fieldset
585             'comment' => 'please fill in', #message at the top of the fieldset
586             'footer' => '* - required',}; #message at the bottom of the fieldset
587             };
588             my $fieldset = $form->add_fieldset($fieldset_attributes);
589              
590             ####################################
591             #Create the input fields.
592             ####################################
593             #When creating an input fields, there are 4 supported keys.
594             #The keys are label, input, error, comment
595             # Label define the title of the input field
596             # Input define and create the actual input type
597             # In input fields, you can defined a key 'heading', which create a text before the input is displayed,
598             # however, if the input type is radio the text is behind the radio box
599             # Error message that go together with the input field when fail in validation
600             # Comment is the message added to explain the input field.
601              
602             ####################################
603             ###Creating a input text
604             ####################################
605              
606             my $input_text = {'label' => {'text' => 'Register Name', for => 'name'},
607             'input' => {'type' => 'text', 'value' => 'John', 'id' => 'name', 'name' => 'name', 'maxlength' => '22'},
608             'error' => { 'id' => 'error_name' ,'text' => 'Name must be in alphanumeric', 'class' => 'errorfield hidden'},
609             'comment' => {'text' => 'Please tell us your name'}};
610              
611             ####################################
612             ###Creating a select option
613             ####################################
614             my @options;
615             push @options, {'value' => 'Mr', 'text' => 'Mr'};
616             push @options, {'value' => 'Mrs', 'text' => 'Mrs'};
617              
618             my $input_select = {'label' => {'text' => 'Title', for => 'mrms'},
619             'input' => {'type' => 'select', 'id' => 'mrms', 'name' => 'mrms', 'options' => \@options},
620             'error' => {'text' => 'Please select a title', 'class' => 'errorfield hidden'}};
621              
622              
623             ####################################
624             ###Creating a hidden value
625             ####################################
626             my $input_hidden = {'input' => {'type' => 'hidden', 'value' => 'John', 'id' => 'name', 'name' => 'name'}};
627              
628             ####################################
629             ###Creating a submit button
630             ####################################
631             my $input_submit_button = {'input' => {'type' => 'submit', 'value' => 'Submit Form', 'id' => 'submit', 'name' => 'submit'}};
632              
633             ###NOTES###
634             Basically, you just need to change the type to the input type that you want and generate parameters with the input type's attributes
635              
636             ###########################################################
637             ###Having more than 1 input field in a single row
638             ###########################################################
639             my $input_select_dobdd = {'type' => 'select', 'id' => 'dobdd', 'name' => 'dobdd', 'options' => \@ddoptions};
640             my $input_select_dobmm = {'type' => 'select', 'id' => 'dobmm', 'name' => 'dobmm', 'options' => \@mmoptions};
641             my $input_select_dobyy = {'type' => 'select', 'id' => 'dobyy', 'name' => 'dobyy', 'options' => \@yyoptions};
642             my $input_select = {'label' => {'text' => 'Birthday', for => 'dobdd'},
643             'input' => [$input_select_dobdd, $input_select_dobmm, $input_select_dobyy],
644             'error' => {'text' => 'Invalid date.'}};
645              
646             #Then we add the input field into the Fieldset
647             #You can add using index of the fieldset
648             $fieldset->add_field($input_text);
649             $fieldset->add_field($input_select);
650             $fieldset->add_field($input_submit_button);
651              
652             ###########################################################
653             ### Field value accessors
654             ###########################################################
655             $form->set_field_value('name', 'Omid');
656             $form->get_field_value('name'); # Returns 'Omid'
657              
658             ###########################################################
659             ### Error message accessors
660             ###########################################################
661             $form->set_field_error_message('name', 'Your name is not good :)');
662             # or
663             $form->set_field_error_message('error_name', 'Your name is not good :)');
664              
665             $form->get_field_error_message('name'); # Return 'Your name is not good :)'
666             # or
667             $form->get_field_error_message('error_name'); # Return 'Your name is not good :)'
668              
669             #Finally, we output the form
670             print $form->build();
671              
672              
673             =head2 A full sample result
674              
675             <form id="onlineIDForm" method="post" action="">
676             <fieldset id="fieldset_one" name="fieldset_one" class="formclass">
677             <div>
678             <label for="name">Register Name</label>
679             <em>:</em>
680             <input type="text" value="John" id="name" name="name">
681             <p id = "error_name" class="errorfield hidden">Name must be in alphanumeric</p>
682             <p>Please tell us your name</p>
683             </div>
684             <div>
685             <label for="mrms">Title</label>
686             <em>:</em>
687             <select id="mrms" name="mrms">
688             <option value="Mr">Mr</option>
689             <option value="Mrs">Mrs</option>
690             </select>
691             <p class="errorfield hidden">Please select a title</p>
692             </div>
693             <div>
694             <label for="dob">Birthday</label>
695             <em>:</em>
696             <select id="dobdd" name="dobdd">
697             <option value="1">1</option>
698             <option value="2">2</option>
699             </select>
700             <select id="dobmm" name="dobmm">
701             <option value="1">Jan</option>
702             <option value="2">Feb</option>
703             </select>
704             <select id="dobyy" name="dobyy">
705             <option value="1980">1980</option>
706             <option value="1981">1981</option>
707             </select>
708             <p class="errorfield hidden">Invalid date</p>
709             </div>
710             <div>
711             <input type="submit" value="Submit Form" id="submit" name="submit">
712             </div>
713             </fieldset>
714             </form>
715              
716             =head2 How to create a form with validation
717              
718             Please refer to <HTML::FormBuilder::Validation>
719              
720             =head2 CROSS SITE REQUEST FORGERY PROTECTION
721              
722             read <HTML::FormBuilder::Validation> for more details
723              
724             =head1 AUTHOR
725              
726             Chylli L<chylli@binary.com>
727              
728             =head1 CONTRIBUTOR
729              
730             Fayland Lam L<fayland@binary.com>
731              
732             Tee Shuwn Yuan L<shuwnyuan@binary.com>
733              
734             =head1 COPYRIGHT AND LICENSE
735              
736             =cut
737