File Coverage

blib/lib/Rose/HTML/Form.pm
Criterion Covered Total %
statement 714 833 85.7
branch 325 494 65.7
condition 56 100 56.0
subroutine 103 118 87.2
pod 64 88 72.7
total 1262 1633 77.2


line stmt bran cond sub pod time code
1              
2             use strict;
3 8     8   428861  
  8         48  
  8         206  
4             use Carp;
5 8     8   36  
  8         134  
  8         490  
6             use Clone::PP;
7 8     8   1977 use Rose::URI;
  8         3499  
  8         41  
8 8     8   3721 use Scalar::Util();
  8         143996  
  8         248  
9 8     8   51 use URI::Escape qw(uri_escape);
  8         17  
  8         162  
10 8     8   37  
  8         15  
  8         404  
11             use Rose::HTML::Util();
12 8     8   2295 use Rose::HTML::Object::Errors qw(:form);
  8         18  
  8         173  
13 8     8   2138  
  8         19  
  8         53  
14             our @ISA = qw(Rose::HTML::Object::WithWrapAroundChildren
15             Rose::HTML::Form::Field Rose::HTML::Form::Field::Collection);
16              
17             our $VERSION = '0.624';
18              
19             # Avoid problems caused by circular dependencies by loading these
20             # modules at runtime. XXX: This whole hierarchy needs an overhaul.
21             require Rose::HTML::Form::Field;
22             require Rose::HTML::Form::Field::Collection;
23             require Rose::HTML::Object::WithWrapAroundChildren;
24              
25             # Multiple inheritence never quite works out the way I want it to...
26             Rose::HTML::Form::Field::Collection->import_methods
27             (
28             'xhtml',
29             'html',
30             'prepare',
31             'hidden_field',
32             'hidden_fields',
33             'html_hidden_field',
34             'xhtml_hidden_field',
35             'html_hidden_fields',
36             'xhtml_hidden_fields',
37             );
38              
39             __PACKAGE__->add_valid_html_attrs
40             (
41             'action', # %URI; #REQUIRED -- server-side form handler --
42             'method', # (GET|POST) GET -- HTTP method used to submit the form--
43             'enctype', # %ContentType; "application/x-www-form-urlencoded"
44             'accept', # %ContentTypes; #IMPLIED -- list of MIME types for file upload --
45             'name', # CDATA #IMPLIED -- name of form for scripting --
46             'onsubmit', # %Script; #IMPLIED -- the form was submitted --
47             'onreset', # %Script; #IMPLIED -- the form was reset --
48             'accept-charset', # %Charsets; #IMPLIED -- list of supported charsets --
49             'target', # http://www.w3.org/TR/xhtml-modularization/abstract_modules.html#s_targetmodule
50             'novalidate',
51             );
52              
53             __PACKAGE__->add_required_html_attrs(
54             {
55             action => '',
56             method => 'get',
57             enctype => 'application/x-www-form-urlencoded',
58             });
59              
60             use constant UNSAFE_URI_CHARS => '^\w\d?\057=.:-';
61 8     8   64  
  8         14  
  8         453  
62             use Rose::HTML::Form::Constants qw(FF_SEPARATOR);
63 8     8   2658  
  8         18  
  8         1036  
64             # Variable for use in regexes
65             our $FF_SEPARATOR_RE = quotemeta FF_SEPARATOR;
66              
67             our $Debug = 0;
68              
69             use Rose::Object::MakeMethods::Generic
70             (
71             scalar =>
72 8         89 [
73             'uri_base',
74             'rank',
75             ],
76              
77             'scalar --get_set_init' =>
78             [
79             'uri_separator',
80             'form_rank_counter',
81             'recursive_init_fields',
82             ],
83              
84             boolean =>
85             [
86             'coalesce_query_string_params' => { default => 1 },
87             'build_on_init' => { default => 1 },
88             ],
89             );
90 8     8   59  
  8         11  
91             #
92             # Class data
93             #
94              
95             use Rose::Class::MakeMethods::Generic
96             (
97             inheritable_scalar =>
98 8         54 [
99             '_delegate_to_subforms',
100             ],
101              
102             inheritable_boolean =>
103             [
104             'default_recursive_init_fields',
105             'default_trim_xy_params',
106             ],
107             );
108 8     8   6872  
  8         13  
109             __PACKAGE__->delegate_to_subforms('compile');
110             __PACKAGE__->default_recursive_init_fields(0);
111             __PACKAGE__->default_trim_xy_params(1);
112              
113             #
114             # Class methods
115             #
116              
117             {
118             my($class) = shift;
119              
120 90     90 1 23921 my $self =
121             {
122 90         399 params => {},
123             fields => {},
124             validate_field_html_attrs => 1,
125             };
126              
127             bless $self, $class;
128              
129 90         207 $self->init(@_);
130              
131 90         379 return $self;
132             }
133 90         1852  
134              
135             {
136 70     70 0 614 my($self) = shift;
137              
138             if(@_)
139             {
140 161     161 1 249 my $val = $self->{'trim_xy_params'} = $_[0] ? 1 : 0;
141              
142 161 100       336 foreach my $form ($self->forms)
143             {
144 4 50       11 $form->trim_xy_params($val);
145             }
146 4         7  
147             return $val;
148 2         6 }
149              
150             return defined $self->{'trim_xy_params'} ?
151 4         7 $self->{'trim_xy_params'} : ref($self)->default_trim_xy_params;
152             }
153              
154             {
155 157 100       724 my($class) = shift;
156              
157             $class = ref $class if(ref $class);
158              
159             if(@_)
160 11     11 1 24 {
161             my $value = shift;
162 11 50       38  
163             # Dumb regex to avoid non-numeric comparison warning
164 11 100       53 $value = 'runtime' if($value =~ /\d/ && $value == 1);
165              
166 8         21 unless(!$value || $value eq 'compile' || $value eq 'runtime')
167             {
168             croak "Invalid delegate_to_subforms() value: '$value'";
169 8 50 33     41 }
170              
171 8 50 33     72 return $class->_delegate_to_subforms($value);
      33        
172             }
173 0         0  
174             return $class->_delegate_to_subforms;
175             }
176 8         40  
177             #
178             # Object methods
179 3         14 #
180              
181              
182             {
183             my($self) = shift;
184              
185             $self->SUPER::init(@_);
186 1     1 0 10  
187             $self->build_form() if($self->build_on_init);
188             }
189              
190 90     90 1 175  
191              
192 90         379  
193             {
194 90 100       612 my($self) = shift;
195              
196             if(@_)
197 13     13 1 53 {
198 2     2 1 15 return $self->html_attr('name', shift);
199             }
200 1     1 0 759 else
201 1     1 0 5 {
202             unless(defined $self->html_attr('name'))
203       49 1   {
204             return $self->form_name;
205             }
206              
207 94     94 1 156 return $self->html_attr('name');
208             }
209 94 100       172 }
210              
211 2         30 {
212             my($self) = shift;
213              
214             if(@_)
215 92 100       196 {
216             foreach my $field ($self->fields)
217 2         8 {
218             $field->validate_html_attrs(@_);
219             }
220 90         153  
221             return $self->{'validate_field_html_attrs'} = $_[0] ? 1 : 0;
222             }
223              
224             return $self->{'validate_field_html_attrs'};
225             }
226 0     0 1 0  
227             # Override inherited, non-public methods with fast-returning
228 0 0       0 # "don't care" versions.
229              
230 0         0  
231             {
232 0         0 my($self) = shift;
233              
234             foreach my $field ($self->fields)
235 0 0       0 {
236             return 0 unless($field->is_empty);
237             }
238 0         0  
239             foreach my $form ($self->forms)
240             {
241             return 0 unless($form->is_empty);
242             }
243 0     0   0  
244       0     return 1;
245 0     0 1 0 }
246              
247 0 0 0 0 1 0 {
248 3     3 0 7 my($self) = shift;
249 0     0 0 0  
250             if(@_)
251             {
252             foreach my $form ($self->forms)
253 98     98 1 148 {
254             $form->empty_is_ok(@_);
255 98         200 }
256              
257 172 100       679 return $self->SUPER::empty_is_ok(@_);
258             }
259              
260 33         184 my $ok = $self->SUPER::empty_is_ok(@_);
261             return $ok unless($ok);
262 11 50       28  
263             foreach my $form ($self->forms)
264             {
265 33         110 return 0 unless($form->empty_is_ok);
266             }
267              
268             return $ok;
269             }
270 95     95 1 154  
271             # Empty contents instead of replacing ref
272 95 100       209  
273             {
274 8         20 my($self, $cgi) = @_;
275              
276 2         11 croak "Missing CGI argument to params_from_cgi" unless(@_ > 1);
277              
278             unless(UNIVERSAL::isa($cgi, 'CGI') || UNIVERSAL::can($cgi, 'param'))
279 8         28 {
280             croak "Argument to params_from_cgi() is not a CGI object and ",
281             "does not have a param() method";
282 87         287 }
283 87 100       694  
284             my %params;
285 10         22  
286             local $CGI::LIST_CONTEXT_WARN = 0;
287 2 50       7  
288             foreach my $param ($cgi->param)
289             {
290 10         44 my @values = $cgi->param($param);
291             $params{$param} = @values > 1 ? \@values : $values[0];
292             }
293              
294 2     2 1 17 $self->params(\%params);
  2         8  
295             }
296              
297             # IIn a reasonably modern perl, the optimizer will eliminate the
298 3     3 1 27324 # blocks of code that are conditional upon these constants when the
299             # value is zero.
300 3 50       12 use constant MP2 => exists $ENV{'MOD_PERL_API_VERSION'} &&
301             $ENV{'MOD_PERL_API_VERSION'} > 1 ? 1 : 0;
302 3 50 66     28  
303             use constant MP1 => # Special environment variable for the test suite
304 0         0 ($ENV{'MOD_PERL'} || $ENV{'RHTMLO_TEST_MOD_PERL'}) &&
305             (!exists $ENV{'MOD_PERL_API_VERSION'} || $ENV{'MOD_PERL_API_VERSION'} == 1) ?
306             1 : 0;
307              
308 3         7 use constant MP0 => $ENV{'MOD_PERL'} ? 0 : 1;
309              
310 3         6 my $Loaded_APR1 = 0;
311             my $Loaded_APR2 = 0;
312 3         11  
313             {
314 7         47 my($self, $apr) = @_;
315 7 100       86  
316             croak "Missing apache request argument to params_from_apache" unless(@_ > 1);
317              
318 3         11 if(MP0)
319             {
320             unless(UNIVERSAL::can($apr, 'param'))
321             {
322             croak "Argument to params_from_apache() does not have a param() method";
323             }
324             }
325 8 50 33 8   10212 elsif(MP1)
  8         21  
  8         674  
326             {
327             if(UNIVERSAL::isa($apr, 'Apache'))
328             {
329 8 100 66     574 unless($Loaded_APR1) # cheaper than require (really!)
330 8     8   47 {
  8         13  
331             require Apache::Request;
332 8 50   8   57 $Loaded_APR1 = 1;
  8         29  
  8         4321  
333             }
334              
335             $apr = Apache::Request->instance($apr);
336             }
337             elsif(!UNIVERSAL::isa($apr, 'Apache::Request') &&
338             !UNIVERSAL::can($apr, 'param'))
339 2     2 1 289 {
340             croak "Argument to params_from_apache() is not an Apache or ",
341 2 50       9 "Apache::Request object and does not have a param() method";
342             }
343 2         4 }
344             elsif(MP2)
345 2 50       11 {
346             if(UNIVERSAL::isa($apr, 'Apache2::RequestRec'))
347 0         0 {
348             unless($Loaded_APR2) # cheaper than require (really!)
349             {
350             require Apache2::Request;
351             $Loaded_APR2 = 1;
352             }
353              
354             $apr = Apache2::Request->new($apr);
355             }
356             elsif(!UNIVERSAL::isa($apr, 'Apache2::Request') &&
357             !UNIVERSAL::can($apr, 'param'))
358             {
359             croak "Argument to params_from_apache() is not an Apache2::RequestRec ",
360             "or Apache2::Request object and does not have a param() method";
361             }
362             }
363              
364             my %params;
365              
366             foreach my $param ($apr->param)
367             {
368             my @values = $apr->param($param);
369             $params{$param} = @values > 1 ? \@values : $values[0];
370             }
371              
372             $self->params(\%params);
373             }
374              
375             {
376             my($self) = shift;
377              
378             if(@_)
379             {
380             if(@_ == 1 && ref $_[0] eq 'HASH')
381             {
382             $self->{'params'} = $_[0];
383             }
384             elsif(@_ % 2 == 0)
385             {
386             $self->{'params'} = Clone::PP::clone({ @_ });
387             }
388             else
389 2         4 {
390             croak(ref($self), '::params() - got odd number of arguments: ');
391 2         6 }
392              
393 5         27 if($self->trim_xy_params)
394 5 100       38 {
395             foreach my $param (keys %{$self->{'params'}})
396             {
397 2         7 if($param =~ /^(.+)\.[xy]$/)
398             {
399             delete $self->{'params'}{$param};
400             $self->{'params'}{$1} = 1;
401             }
402 191     191 1 7560 }
403             }
404 191 100       406  
405             foreach my $form ($self->forms)
406 157 100 66     613 {
    50          
407             $form->params($self->{'params'});
408 140         281 }
409             }
410              
411             my $want = wantarray;
412 17         131 return unless(defined $want);
413              
414             return ($want) ? %{ Clone::PP::clone($self->{'params'}) } : $self->{'params'};
415             }
416 0         0  
417             {
418             my($self, $param) = @_;
419 157 100       1833  
420             no warnings;
421 153         2551  
  153         440  
422             return exists $self->{'params'}{$param};
423 704 100       1575 }
424              
425 1         3  
426 1         3 {
427             my($self, $name) = @_;
428              
429             $name = $name->name if(UNIVERSAL::isa($name, 'Rose::HTML::Form::Field'));
430              
431 157         369 return 0 unless($self->field($name));
432              
433 87         226 my $nibble = $name;
434             my $found_form = 0;
435              
436             while(length $nibble)
437 191         282 {
438 191 100       407 if($self->form($nibble) && !$self->field($nibble))
439             {
440 34 100       151 $found_form = 1;
  1         7  
441             last;
442             }
443              
444             return 1 if($self->param_exists($nibble));
445 1641     1641 1 2532 $nibble =~ s/\.[^.]+$// || last;
446             }
447 8     8   52  
  8         13  
  8         7943  
448             foreach my $field ($found_form ? $self->form($nibble)->fields :
449 1641         3006 $self->field($name))
450             {
451             if($field->can('subfield_names'))
452 0 0   0 1 0 {
  0         0  
453             foreach my $subname ($field->subfield_names)
454             {
455             # Skip unrelated subfields
456 36     36 1 91 next unless(index($name, $subname) == 0 ||
457             index($subname, $name) == 0);
458 36 100       180  
459             return 1 if($self->param_exists($subname));
460 36 100       84 }
461             }
462 34         55 }
463 34         48  
464             return 0;
465 34         59 }
466              
467 62 100 66     108 {
468             my($self, $param, $value) = @_;
469 11         16  
470 11         19 croak(ref($self), '::param_value_exists() requires a param name plus a value')
471             unless(@_ == 3);
472              
473 51 100       95 $param = $self->param($param);
474 40 100       184  
475             return 0 unless($param);
476              
477 23 100       57 foreach my $existing_value ((ref $param) ? @$param : $param)
478             {
479             return 1 if($existing_value eq $value);
480 23 100       66 }
481              
482 20         59 return 0;
483             }
484              
485 102 100 100     283 {
486             my($self, $param, $value) = @_;
487              
488 83 100       117 if(@_ == 2)
489             {
490             if(exists $self->{'params'}{$param})
491             {
492             if(wantarray)
493 13         86 {
494             if(ref $self->{'params'}{$param})
495             {
496             return @{$self->{'params'}{$param}};
497             }
498 3     3 1 7  
499             return ($self->{'params'}{$param});
500 3 50       8 }
501              
502             return $self->{'params'}{$param};
503 3         6 }
504              
505 3 50       7 return;
506             }
507 3 50       11 elsif(@_ == 3)
508             {
509 9 100       20 return $self->{'params'}{$param} = $value;
510             }
511              
512 1         4 croak(ref($self), '::param() requires a param name plus an optional value');
513             }
514              
515             {
516             my($self, $param, @values) = @_;
517 250     250 1 937  
518             croak(ref($self), '::delete_param() requires a param name')
519 250 100       496 unless(@_ >= 2);
    50          
520              
521 249 100       551 @values = @{$values[0]} if(@values == 1 && ref $values[0] eq 'ARRAY');
522              
523 246 100       418 if(@values)
524             {
525 214 100       478 my %values = map { $_ => 1 } @values;
526              
527 9         12 my $current = $self->{'params'}{$param};
  9         42  
528              
529             if(ref $current)
530 205         651 {
531             my @new;
532              
533 32         121 foreach my $val (@$current)
534             {
535             push(@new, $val) unless(exists $values{$val});
536 3         10 }
537              
538             if(@new)
539             {
540 1         4 $self->{'params'}{$param} = @new > 1 ? \@new : $new[0];
541             }
542             else
543 0         0 {
544             delete $self->{'params'}{$param};
545             }
546             }
547             elsif(exists $values{$self->{'params'}{$param}})
548 4     4 1 498 {
549             delete $self->{'params'}{$param};
550 4 50       14 }
551             }
552             else
553 4 100 100     21 {
  1         3  
554             delete $self->{'params'}{$param};
555 4 100       10 }
556             }
557 3         7  
  4         13  
558             {
559 3         9 my($self, $param, $value) = @_;
560              
561 3 100       9 croak(ref($self), '::add_param() requires a param name plus a value')
    50          
562             unless(@_ == 3);
563 2         4  
564             my $current = $self->{'params'}{$param};
565 2         3  
566             if(ref $current)
567 7 100       92 {
568             push(@$current, ((ref $value) ? @$value : $value));
569             }
570 2 50       7 elsif(defined $current)
571             {
572 2 100       12 $current = [ $current, ((ref $value) ? @$value : $value) ];
573             }
574             else
575             {
576 0         0 $current = [ ((ref $value) ? @$value : $value) ];
577             }
578              
579             $self->{'params'}{$param} = $current;
580             }
581 1         4  
582             {
583             my($self) = shift;
584              
585             my $uri_root = $self->uri_base . $self->html_attr('action');
586 1         4  
587             my $self_uri = $uri_root;
588              
589             if(keys %{$self->{'params'}})
590             {
591             $self_uri .= '?' unless($self_uri =~ /\?$/);
592 1     1 1 4 $self_uri .= $self->query_string;
593             }
594 1 50       4  
595             return Rose::URI->new($self_uri);
596             }
597 1         3  
598             # XXX: To document or not to document, that is the question...
599 1 50       3  
    0          
600             {
601 1 50       4 my($self) = shift;
602              
603             my $coalesce = $self->coalesce_query_string_params;
604              
605 0 0       0 my %params;
606              
607             my @fields = $self->fields;
608              
609 0 0       0 while(my $field = shift(@fields))
610             {
611             unless($coalesce)
612 1         2 {
613             if($field->isa('Rose::HTML::Form::Field::Compound'))
614             {
615             unshift(@fields, $field->fields);
616             next;
617 1     1 1 8 }
618             }
619 1         6  
620             my $value = $field->output_value;
621 1         3 next unless(defined $value);
622             push(@{$params{$field->name}}, ref $value ? @$value : $value);
623 1 50       2 }
  1         4  
624              
625 0 0       0 my $qs = '';
626 0         0 my $sep = $self->uri_separator;
627              
628             no warnings;
629 1         8  
630             foreach my $param (sort keys(%params))
631             {
632             my $values = $params{$param};
633 0     0 0 0  
634             $qs .= $sep if($qs);
635             $qs .= join($sep, map { $param . '=' . uri_escape($_, UNSAFE_URI_CHARS) } @$values);
636             }
637 4     4 1 9  
638             return $qs;
639 4         16 }
640              
641 4         22 {
642             my($self, %args) = @_;
643 4         10  
644             $args{'cascade'} = 1 unless(exists $args{'cascade'});
645 4         13  
646             my $fail = 0;
647 19 100       32  
648             my $cascade = $args{'cascade'};
649 9 100       36  
650             if($cascade)
651 1         6 {
652 1         3 foreach my $form ($self->forms)
653             {
654             next if($form->is_empty && $form->empty_is_ok);
655              
656 18         56 $Debug && warn "Validating sub-form ", $form->form_name, "\n";
657 18 100       43  
658 16 100       17 unless($form->validate(%args))
  16         40  
659             {
660             $self->add_error($form->error) if($form->error);
661 4         6 $fail++;
662 4         13 }
663             }
664 8     8   52 }
  8         21  
  8         6041  
665              
666 4         31 unless($args{'form_only'})
667             {
668 16         569 return 1 if($self->is_empty && $self->empty_is_ok);
669              
670 16 100       29 foreach my $field ($self->fields)
671 16         25 {
  20         125  
672             if($field->parent_form ne $self)
673             {
674 4         90 $Debug && warn "Skipping validation of field ", $field->name, " in child form\n";
675             }
676             else
677             {
678             $Debug && warn "Validating ", $field->name, "\n";
679 55     55 1 291 $fail++ unless($field->validate);
680             }
681 55 100       265 }
682             }
683 55         89  
684             if($fail)
685 55         75 {
686             unless($self->has_errors)
687 55 100       102 {
688             $self->add_error_id(FORM_HAS_ERRORS);
689 51         111 }
690              
691 32 100 100     98 return 0;
692             }
693 30 50       68  
694             return 1;
695 30 100       126 }
696              
697 5 100       15 {
698 5         12 my($self) = shift;
699              
700             $self->params_from_cgi(shift);
701             $self->init_fields(@_);
702             }
703 55 100       139  
704             {
705 52 100 100     122 my($self) = shift;
706              
707 50         116 $self->params_from_apache(shift);
708             $self->init_fields(@_);
709 254 100       485 }
710              
711 136 50       240 {
712             my($self, %args) = @_;
713              
714             $self->clear() unless($args{'no_clear'});
715 118 50       207  
716 118 100       325 if(exists $args{'recursive'} ? $args{'recursive'} : $self->recursive_init_fields)
717             {
718             foreach my $field ($self->local_fields)
719             {
720             $self->_init_field($field);
721 53 100       133 }
722              
723 13 100       88 foreach my $form ($self->forms)
724             {
725 9         54 $form->init_fields;
726             }
727             }
728 13         59 else
729             {
730             foreach my $field ($self->fields)
731 40         122 {
732             $self->_init_field($field);
733             }
734             }
735             }
736 1     1 1 3  
737             {
738 1         4 my($self, $field) = @_;
739 1         5  
740             my $on_off = $field->isa('Rose::HTML::Form::Field::OnOff');
741              
742             my $name = $field->name;
743             my $moniker = $field->moniker;
744 1     1 1 4 my $name_attr = $field->html_attr('name');
745              
746 1         4 $Debug && warn "INIT FIELD $name ($name_attr)\n";
747 1         3  
748             my $name_exists = $self->param_exists($name);
749             my $moniker_exists = $self->param_exists($moniker);
750             my $name_attr_exists = $self->param_exists($name_attr);
751              
752 116     116 1 318 if(!$name_exists && $field->isa('Rose::HTML::Form::Field::Compound'))
753             {
754 116 100       536 foreach my $moniker ($field->field_monikers)
755             {
756 116 50       455 $self->_init_field($field->field($moniker));
    100          
757             }
758 78         623 }
759             else
760 182         363 {
761             return unless($name_exists || $name_attr_exists || $moniker_exists || $on_off);
762              
763 78         204 if($field->isa('Rose::HTML::Form::Field::Group'))
764             {
765 60         202 if($name_exists)
766             {
767             $Debug && warn "$field->input_value(", $self->param($name), ")\n";
768             $field->input_value($self->param($name));
769             }
770 38         262 elsif($moniker_exists)
771             {
772 175         311 $Debug && warn "$field->input_value(", $self->param($moniker), ")\n";
773             $field->input_value($self->param($moniker));
774             }
775             else
776             {
777             $Debug && warn "$field->input_value(", $self->param($name_attr), ")\n";
778             $field->input_value($self->param($name_attr));
779 501     501   749 }
780             }
781 501         1612 else
782             {
783 501         1132 # Must handle lone checkboxes and radio buttons here
784 501         1140 if($on_off)
785 501         980 {
786             no warnings 'uninitialized';
787 501 50       921 if($name_exists && $self->param($name) eq $field->html_attr('value'))
788             {
789 501         1037 $Debug && warn "$self->param($name) = checked\n";
790 501         751 $field->checked(1);
791 501         754 }
792             else
793 501 100 100     1649 {
794             if($self->params_exist)
795 48         155 {
796             $field->checked(0);
797 144         315 }
798             else
799             {
800             # Didn't set anything, so avoid doing pareant un-clearing below
801             return;
802 453 100 66     1712 }
      100        
      66        
803             }
804 214 100       662 }
805             else
806 41 50       89 {
    0          
807             if($name_exists)
808 41 50       97 {
809 41         96 $Debug && warn "$field->input_value(", $self->param($name), ")\n";
810             $field->input_value($self->param($name));
811             }
812             elsif($moniker_exists)
813 0 0       0 {
814 0         0 $Debug && warn "$field->input_value(", $self->param($moniker), ")\n";
815             $field->input_value($self->param($moniker));
816             }
817             else
818 0 0       0 {
819 0         0 $Debug && warn "$field->input_value(", $self->param($name_attr), ")\n";
820             $field->input_value($self->param($name_attr));
821             }
822             }
823             }
824             }
825 173 50       273  
826             my $parent = $field->parent_field;
827 8     8   56  
  8         23  
  8         16551  
828 0 0 0     0 # Ensure that setting the value of a child field makes all its
829             # parent fields "not cleared"
830 0 0       0 while($parent)
831 0         0 {
832             $parent->is_cleared(0);
833             $parent = $parent->parent_field;
834             }
835 0 0       0 }
836              
837 0         0 {
838             my($self) = shift;
839              
840             foreach my $field ($self->fields)
841             {
842 0         0 return 1 if($self->param_exists_for_field($field->name));
843             }
844              
845             return 0;
846             }
847              
848 173 100       280 {
    50          
849             my($self) = shift;
850 172 50       300 return '<' . ref($self)->html_element . $self->html_attrs_string() . '>';
851 172         516 }
852              
853             *start_xhtml = \&start_html;
854              
855 1 50       4 {
856 1         7 my($self) = shift;
857             $self->html_attr(enctype => 'multipart/form-data');
858             return $self->start_html;
859             }
860 0 0       0  
861 0         0 *start_multipart_xhtml = \&start_multipart_html;
862              
863              
864             *end_xhtml = \&end_html;
865             *end_multipart_xhtml = \&end_multipart_html;
866              
867 262         595 {
868             my($self) = shift;
869              
870             my($class, $object);
871 262         794  
872             if(@_ == 1)
873 54         138 {
874 54         219 $class = shift;
875              
876             if(ref $class)
877             {
878             $object = $class;
879             $class = ref $object;
880 0     0 1 0 }
881             }
882 0         0 elsif(@_)
883             {
884 0 0       0 my %args = @_;
885              
886             $class = $args{'class'};
887 0         0 $object = $args{'object'};
888             }
889             else
890             {
891             croak "Missing required object class argument";
892 11     11 1 137 }
893 11         41  
894             $object ||= $class->new();
895              
896             # Special handling of boolean columns for RDBO
897             if($object->isa('Rose::DB::Object'))
898             {
899             my $meta = $object->meta;
900 2     2 1 5  
901 2         7 FIELD: foreach my $field ($self->fields)
902 2         5 {
903             my $name = $field->local_name;
904              
905             # When more than one field has the same local_name(), fields closer
906             # to the parent form take precedence.
907 8     8 1 67 my $check_name = $field->name;
908 2     2 1 8  
909             # Remove the form name context, if any
910             if(defined(my $form_name_context = $self->form_name_context))
911             {
912             $check_name =~ s/^$form_name_context//;
913             }
914              
915 19     19 1 9386 if($check_name ne $name)
916             {
917 19         30 while($check_name =~ s/(^.+$FF_SEPARATOR_RE|^)[^$FF_SEPARATOR_RE]+$FF_SEPARATOR_RE([^$FF_SEPARATOR_RE]+)$/$1$2/)
918             {
919 19 100       58 next FIELD if($self->field($check_name));
    50          
920             }
921 16         28 }
922              
923 16 100       44 if($object->can($name))
924             {
925 2         5 # Checkboxes setting boolean columns
926 2         4 if($field->isa('Rose::HTML::Form::Field::Checkbox') &&
927             $meta->column($name) && $meta->column($name)->type eq 'boolean')
928             {
929             #$Debug && warn "$class object $name(", $field->is_on, ")";
930             $object->$name($field->is_on);
931 3         11 }
932             else # everything else
933 3         9 {
934 3         10 #$Debug && warn "$class object $name(", $field->internal_value, ")";
935             $object->$name($field->internal_value);
936             }
937             }
938 0         0 }
939             }
940             else
941 19   66     129 {
942             FIELD: foreach my $field ($self->fields)
943             {
944 19 50       289 my $name = $field->local_name;
945              
946 0         0 # When more than one field has the same local_name(), fields closer
947             # to the parent form take precedence.
948 0         0 my $check_name = $field->name;
949              
950 0         0 # Remove the form name context, if any
951             if(defined(my $form_name_context = $self->form_name_context))
952             {
953             $check_name =~ s/^$form_name_context//;
954 0         0 }
955              
956             if($check_name ne $name)
957 0 0       0 {
958             while($check_name =~ s/(^.+$FF_SEPARATOR_RE|^)[^$FF_SEPARATOR_RE]+$FF_SEPARATOR_RE([^$FF_SEPARATOR_RE]+)$/$1$2/)
959 0         0 {
960             next FIELD if($self->field($check_name));
961             }
962 0 0       0 }
963              
964 0         0 if($object->can($name))
965             {
966 0 0       0 #$Debug && warn "$class object $name(", $field->internal_value, ")";
967             $object->$name($field->internal_value);
968             }
969             }
970 0 0       0 }
971              
972             return $object;
973 0 0 0     0 }
      0        
974              
975             *init_object_with_form = \&object_from_form;
976              
977 0         0 {
978             my($self, $object) = @_;
979              
980             croak "Missing required object argument" unless($object);
981              
982 0         0 $self->clear();
983              
984             foreach my $field ($self->fields)
985             {
986             my $name = $field->local_name;
987              
988             if($object->can($name))
989 19         69 {
990             #$Debug && warn "field($name) = $object->$name = ", $object->$name();
991 126         365 $field->input_value(scalar $object->$name());
992             }
993             }
994             }
995 126         283  
996             {
997             my($self) = shift;
998 126 100       265 $self->clear_fields;
999             $self->clear_forms;
1000 18         137 $self->error(undef);
1001             }
1002              
1003 126 100       238 {
1004             my($self) = shift;
1005 63         637 $self->reset_fields;
1006             $self->reset_forms;
1007 126 100       281 $self->error(undef);
1008             }
1009              
1010              
1011 123 100       471 {
1012             my($self) = shift;
1013              
1014 69         181 my $rank = 1;
1015              
1016             foreach my $form ($self->forms)
1017             {
1018             $rank = $form->rank + 1 if($form->rank >= $rank);
1019 19         122 }
1020              
1021             return $rank;
1022             }
1023              
1024             # XXX: Remove when form_rank_counter is removed
1025             {
1026 4     4 1 1977 my($self) = shift;
1027             my $rank = $self->form_rank_counter;
1028 4 50       13 $self->form_rank_counter($rank + 1);
1029             return $rank;
1030 4         15 }
1031              
1032 4         10 {
1033             my($self) = shift;
1034 15         37  
1035             # Set form
1036 15 100       81 if(@_ > 1)
1037             {
1038             my($name, $form) = (shift, shift);
1039 5         24 $self->delete_repeatable_form($name);
1040             return $self->add_repeatable_form($name => $form);
1041             }
1042              
1043             my $form = $self->form(@_) or return undef;
1044             return undef unless($form->is_repeatable);
1045             return $form;
1046 307     307 1 429 }
1047 307         886  
1048 307         1789 {
1049 307         691 my($self) = shift;
1050              
1051             if(@_)
1052             {
1053             $self->delete_repeatable_forms;
1054 4     4 1 2993 $self->add_repeatable_forms(@_);
1055 4         22 return unless(defined wantarray);
1056 4         20 }
1057 4         9  
1058             return wantarray ?
1059             (grep { $_->is_repeatable_form } $self->forms(@_)) :
1060 34     34 0 319 [ grep { $_->is_repeatable_form } $self->forms(@_) ];
1061             }
1062              
1063             {
1064 71     71 0 116 my($self) = shift;
1065              
1066 71         126 my @form_args;
1067              
1068 71         144 while(@_)
1069             {
1070 44 50       147 my $arg = shift;
1071              
1072             if(UNIVERSAL::isa($arg, 'Rose::HTML::Form'))
1073 71         151 {
1074             push(@form_args,
1075             $arg->form_name =>
1076             {
1077             form => $arg,
1078             repeatable => undef,
1079 40     40 0 64 });
1080 40         141 }
1081 40         175 elsif(!ref $arg)
1082 40         122 {
1083             if(UNIVERSAL::isa($_[0], 'Rose::HTML::Form'))
1084             {
1085             my $form = shift;
1086              
1087 8     8 1 2802 push(@form_args,
1088             $arg =>
1089             {
1090 8 100       28 form => $form,
1091             repeatable => undef,
1092 1         3 });
1093 1         8 }
1094 1         5 elsif(ref $_[0] eq 'HASH')
1095             {
1096             my $spec = shift;
1097 7 50       18 $spec->{'repeatable'} = undef unless(exists $spec->{'repeatable'});
1098 7 50       25 push(@form_args, $arg => $spec);
1099 7         26 }
1100             else
1101             {
1102             croak "Invalid argument pair passed to add_repeatable_forms() - $arg, $_[0]";
1103             }
1104 0     0 1 0 }
1105             else
1106 0 0       0 {
1107             croak "Invalid argument passed to add_repeatable_forms() - $arg";
1108 0         0 }
1109 0         0 }
1110 0 0       0  
1111             return $self->add_forms(@form_args);
1112             }
1113              
1114 0         0  
1115 0 0       0 {
  0         0  
1116             my($self) = shift;
1117              
1118             if(@_)
1119             {
1120 6     6 1 11 return $self->{'form_depth'} = shift;
1121             }
1122 6         12  
1123             return $self->{'form_depth'} if(defined $self->{'form_depth'});
1124 6         18  
1125             my $depth = 0;
1126 6         20 my $form = $self;
1127             $depth++ while($form = $form->parent_form);
1128 6 50       33  
    50          
1129             return $self->{'form_depth'} = $depth;
1130 0         0 }
1131              
1132             {
1133             my($self) = shift;
1134              
1135             my @added_forms;
1136              
1137             my $next_rank = $self->next_form_rank;
1138              
1139 6 100       39 while(@_)
    50          
1140             {
1141 4         12 my $arg = shift;
1142              
1143 4         25 my($name, $form);
1144              
1145             if(UNIVERSAL::isa($arg, 'Rose::HTML::Form'))
1146             {
1147             $form = $arg;
1148              
1149             if(Scalar::Util::refaddr($form) eq Scalar::Util::refaddr($self))
1150             {
1151             croak "Cannot nest a form within itself";
1152 2         4 }
1153 2 50       9  
1154 2         8 $name = $form->form_name;
1155              
1156             croak "Cannot add form $form without a name" unless(defined $name);
1157             croak "Cannot add form with the same name as an existing field: $name"
1158 0         0 if($self->field($name));
1159              
1160             unless(defined $form->rank)
1161             {
1162             $self->increment_form_rank_counter; # XXX: Remove when form_rank_counter is removed
1163 0         0 $form->rank($next_rank++);
1164             }
1165             }
1166             else
1167 6         20 {
1168             $name = $arg;
1169             $form = shift;
1170 6     6 1 41  
1171             croak "Cannot add form with the same name as an existing field: $name"
1172             if($self->field($name));
1173              
1174 8148     8148 0 9188 if(UNIVERSAL::isa($form, 'Rose::HTML::Form'))
1175             {
1176 8148 100       11301 if(Scalar::Util::refaddr($form) eq Scalar::Util::refaddr($self))
1177             {
1178 72         146 croak "Cannot nest a form within itself";
1179             }
1180              
1181 8076 100       32145 # Manually propagate the empty_is_ok attribute to sub-forms, but only if it's set
1182             $form->empty_is_ok(1) if($self->empty_is_ok);
1183 111         200 }
1184 111         194 elsif(ref $form eq 'HASH')
1185 111         257 {
1186             unless(exists $form->{'repeatable'})
1187 111         271 {
1188             croak "Missing key 'repeatable' in hash reference specification for form named '$name'";
1189             }
1190              
1191             my $repeat_spec = $form;
1192 68     68 1 913  
1193             if(ref $form->{'repeatable'})
1194 68         91 {
1195             @$repeat_spec{keys %{$form->{'repeatable'}}} = values %{$form->{'repeatable'}};
1196 68         201 }
1197             else
1198 68         163 {
1199             $repeat_spec->{'default_count'} = $form->{'repeatable'}
1200 74         114 unless(exists $repeat_spec->{'default_count'});
1201             }
1202 74         143  
1203             delete $form->{'repeatable'};
1204 74 100       328  
1205             $repeat_spec->{'prototype_form_spec'} = delete $repeat_spec->{'spec'}
1206 1         2 if($repeat_spec->{'spec'});
1207              
1208 1 50       7 $repeat_spec->{'prototype_form_spec'} = delete $repeat_spec->{'form_spec'}
1209             if($repeat_spec->{'form_spec'});
1210 1         216  
1211             $repeat_spec->{'prototype_form_class'} = delete $repeat_spec->{'class'}
1212             if($repeat_spec->{'class'});
1213 0         0  
1214             $repeat_spec->{'prototype_form_class'} = delete $repeat_spec->{'form_class'}
1215 0 0       0 if($repeat_spec->{'form_class'});
1216 0 0       0  
1217             $repeat_spec->{'prototype_form'} = delete $repeat_spec->{'form'}
1218             if($repeat_spec->{'form'});
1219 0 0       0  
1220             $form = ref($self)->object_type_class_loaded('repeatable form')->new(%$repeat_spec);
1221 0         0  
1222 0         0 # Manually propagate the empty_is_ok attribute to sub-forms, but only if it's set
1223             if($repeat_spec->{'empty_is_ok'} || $self->empty_is_ok)
1224             {
1225             $form->empty_is_ok(1);
1226             }
1227 73         133 }
1228 73         111 else
1229             {
1230 73 50       174 Carp::croak "Not a Rose::HTML::Form object: $form";
1231             }
1232              
1233 73 100       265 $form->form_name($name);
    50          
1234              
1235 59 100       288 unless(defined $form->rank)
1236             {
1237 1         103 $self->increment_form_rank_counter; # XXX: Remove when form_rank_counter is removed
1238             $form->rank($next_rank++);
1239             }
1240             }
1241 58 100       185  
1242             if(index($name, FF_SEPARATOR) >= 0)
1243             {
1244             my($parent_form, $local_name) = $self->choose_parent_form($name);
1245 14 50       41 $form->form_name($local_name);
1246             $form->parent_form($parent_form);
1247 0         0 $parent_form->add_form($local_name => $form);
1248             }
1249             else
1250 14         26 {
1251             $form->parent_form($self);
1252 14 100       44 $self->{'forms'}{$name} = $form;
1253             }
1254 1         8  
  1         8  
  1         6  
1255             push(@added_forms, $form);
1256             }
1257              
1258             my $depth = $self->form_depth + 1;
1259 13 100       41  
1260             foreach my $form (@added_forms)
1261             {
1262 14         25 if($form->recursive_init_fields || $form->isa('Rose::HTML::Form::Repeatable'))
1263             {
1264             $self->recursive_init_fields(1);
1265 14 50       32 }
1266              
1267             $form->form_depth($depth);
1268 14 100       34 $form->resync_field_names;
1269             }
1270              
1271 14 50       28 $self->_clear_form_generated_values;
1272             $self->resync_fields_by_name;
1273              
1274 14 100       34 return unless(defined wantarray);
1275             return @added_forms;
1276             }
1277 14 100       41  
1278             *add_form = \&add_forms;
1279 14         78  
1280             {
1281             my($self) = shift;
1282 14 100 66     77  
1283             foreach my $field ($self->fields)
1284 1         3 {
1285             $field->resync_name;
1286             }
1287              
1288             foreach my $form ($self->forms)
1289 0         0 {
1290             $form->resync_field_names;
1291             }
1292 72         252 }
1293              
1294 72 100       221 {
1295             my($self) = shift;
1296 37         121  
1297 37         104 $self->{'fields_by_name'} = {};
1298              
1299             foreach my $field ($self->fields)
1300             {
1301 72 100       227 $self->{'fields_by_name'}{$field->name} = $field;
1302             }
1303 2         15 }
1304 2         6  
1305 2         6 {
1306 2         8 my($self, $one, $two) = @_;
1307             no warnings 'uninitialized';
1308             return $one->form_depth <=> $two->form_depth || $one->rank <=> $two->rank;
1309             }
1310 70         193  
1311 70         141 {
1312             my($self) = shift;
1313              
1314 72         199 if(@_)
1315             {
1316             $self->delete_forms;
1317 66         176 $self->add_forms(@_);
1318             return unless(defined wantarray);
1319 66         136 }
1320              
1321 72 100 100     220 if(my $forms = $self->{'form_list'})
1322             {
1323 44         934 return wantarray ? @$forms : $forms;
1324             }
1325              
1326 72         939 my $forms = $self->{'forms'};
1327 72         151  
1328             $self->{'form_list'} = [ grep { defined } map { $forms->{$_} } $self->form_names ];
1329              
1330 66         304 return wantarray ? @{$self->{'form_list'}} : $self->{'form_list'};
1331 66         213 }
1332              
1333 66 50       240 {
1334 0         0 my($self) = shift;
1335              
1336             if(my $names = $self->{'form_names'})
1337             {
1338             return wantarray ? @$names : $names;
1339             }
1340              
1341 224     224 0 328 my @info;
1342              
1343 224         545 while(my($name, $form) = each %{$self->{'forms'}})
1344             {
1345 1215         2919 push(@info, [ $name, $form ]);
1346             }
1347              
1348 224         647 $self->{'form_names'} =
1349             [ map { $_->[0] } sort { $self->compare_forms($a->[1], $b->[1]) } @info ];
1350 39         104  
1351             return wantarray ? @{$self->{'form_names'}} : $self->{'form_names'};
1352             }
1353              
1354             {
1355             my($self) = shift;
1356 66     66 0 106  
1357             foreach my $form (grep { $_->is_repeatable_form } $self->forms)
1358 66         165 {
1359             delete $self->{'forms'}{$form->form_name};
1360 66         156 }
1361              
1362 362         756 $self->_clear_form_generated_values;
1363              
1364             return;
1365             }
1366              
1367             {
1368 4005     4005 1 5351 my($self, $name) = @_;
1369 8     8   58  
  8         12  
  8         7798  
1370 4005   100     6030 $name = $name->form_name if(UNIVERSAL::isa($name, 'Rose::HTML::Form'));
1371              
1372             if(exists $self->{'forms'}{$name} && $self->{'forms'}{$name}->is_repeatable_form)
1373             {
1374             my $form = delete $self->{'forms'}{$name};
1375 1692     1692 1 2261  
1376             $self->_clear_form_generated_values;
1377 1692 50       2847  
1378             return $form;
1379 0         0 }
1380 0         0  
1381 0 0       0 return undef;
1382             }
1383              
1384 1692 100       3271 {
1385             my($self) = shift;
1386 1512 100       3886  
1387             foreach my $form (grep { $_->is_repeatable_field } $self->forms)
1388             {
1389 180         285 delete $self->{'forms'}{$form->form_name};
1390             }
1391 180         441  
  119         234  
  119         213  
1392             $self->_clear_form_generated_values;
1393 180 50       360  
  180         405  
1394             return;
1395             }
1396              
1397             {
1398 182     182 1 316 my($self, $name) = @_;
1399              
1400 182 100       424 $name = $name->form_name if(UNIVERSAL::isa($name, 'Rose::HTML::Form'));
1401              
1402 2 50       13 if(exists $self->{'forms'}{$name} && $self->{'forms'}{$name}->is_repeatable_field)
1403             {
1404             $self->_clear_form_generated_values;
1405 180         313 return delete $self->{'forms'}{$name};
1406             }
1407 180         248  
  299         882  
1408             return undef;
1409 119         283 }
1410              
1411             {
1412             my($self) = shift;
1413 180         515  
  119         274  
  52         115  
1414             # Leave the repeatable fields which are implemented as a special case of repeatable forms
1415 180 50       395 foreach my $form (grep { !$_->is_repeatable_field } $self->forms)
  180         490  
1416             {
1417             delete $self->{'forms'}{$form->form_name};
1418             }
1419              
1420 0     0 1 0 $self->form_rank_counter(undef); # XXX: Remove when form_rank_counter is removed
1421             $self->_clear_form_generated_values;
1422 0         0 return;
  0         0  
1423             }
1424 0         0  
1425             {
1426             my($self, $name) = @_;
1427 0         0  
1428             $name = $name->form_name if(UNIVERSAL::isa($name, 'Rose::HTML::Form'));
1429 0         0  
1430             if(exists $self->{'forms'}{$name})
1431             {
1432             my $form = delete $self->{'forms'}{$name};
1433              
1434 4     4 1 1866 $self->_clear_form_generated_values;
1435              
1436 4 50       20 return $form;
1437             }
1438 4 50 33     21  
1439             return undef;
1440 4         11 }
1441              
1442 4         10 {
1443             my($self) = shift;
1444 4         60  
1445             foreach my $form ($self->forms)
1446             {
1447 0         0 $form->clear();
1448             }
1449             }
1450              
1451             {
1452 8     8 0 16 my($self) = shift;
1453              
1454 8         24 foreach my $form ($self->forms)
  0         0  
1455             {
1456 0         0 $form->reset();
1457             }
1458             }
1459 8         30  
1460             {
1461 8         12 my($self) = shift;
1462             $self->{'form_list'} = undef;
1463             $self->{'form_names'} = undef;
1464             $self->{'form_depth'} = undef;
1465             $self->_clear_field_generated_values;
1466 0     0 0 0 }
1467              
1468 0 0       0 {
1469             my($self) = shift;
1470 0 0 0     0  
1471             return $self->{'form_name'} unless(@_);
1472 0         0 my $old_name = $self->{'form_name'};
1473 0         0 my $name = $self->{'form_name'} = shift;
1474             my %forms;
1475              
1476 0         0 if(my $parent_form = $self->parent_form)
1477             {
1478             if(defined $old_name && defined $name && $name ne $old_name)
1479             {
1480             $parent_form->delete_form($old_name);
1481 2     2 1 15 $parent_form->add_form($name => $self);
1482             }
1483             }
1484 2         8  
  3         11  
1485             return $name;
1486 3         5 }
1487              
1488             {
1489 2         10 my($self, $name) = (shift, shift);
1490 2         12  
1491 2         8 if(my $field = shift)
1492             {
1493             $field = $self->make_field($name, $field);
1494              
1495             $field->parent_form($self);
1496 15     15 1 688 no warnings 'uninitialized';
1497             $field->name($name) unless(length $field->name);
1498 15 50       72 $field->moniker($name);
1499             $self->{'fields_by_name'}{$field->name} = $field;
1500 15 100       50 return $self->{'fields'}{$name} = $field;
1501             }
1502 14         27  
1503             return $self->{'fields'}{$name} || $self->{'fields_by_name'}{$name};
1504 14         52 }
1505              
1506 14         47 {
1507             my($self) = shift;
1508             return values %{ $self->{'fields'} || {} };
1509 1         2 }
1510              
1511             {
1512             my($self) = shift;
1513             $self->_clear_field_generated_values;
1514 307     307 0 409 $self->{'fields'} = {};
1515             $self->{'fields_by_name'} = {};
1516 307         543 $self->delete_repeatable_fields;
1517             $self->field_rank_counter(undef);
1518 186         401 return;
1519             }
1520              
1521             {
1522             my($self, $name) = @_;
1523              
1524 4     4 0 6 $name = $name->name if(UNIVERSAL::isa($name, 'Rose::HTML::Form::Field'));
1525              
1526 4         11 $self->_clear_field_generated_values;
1527              
1528 0         0 my $field1 = delete $self->{'fields'}{$name};
1529             my $field2 = delete $self->{'fields_by_name'}{$name};
1530             return $field1 || $field2;
1531             }
1532              
1533             {
1534 94     94   169 my($self, $name) = (shift, shift);
1535 94         194  
1536 94         179 return $self->{'field_cache'}{$name} if($self->{'field_cache'}{$name});
1537 94         147  
1538 94         284 my $sep_pos;
1539              
1540             # Non-hierarchical name
1541             if(($sep_pos = index($name, FF_SEPARATOR)) < 0)
1542             {
1543 8594     8594 1 17106 return $self->{'field_cache'}{$name} = $self->local_field($name, @_);
1544             }
1545 8594 100       20204  
1546 77         126 # First check if it's a local compound field
1547 77         222 my $prefix = substr($name, 0, $sep_pos);
1548 77         121 my $rest = substr($name, $sep_pos + 1);
1549             my $field = $self->field($prefix);
1550 77 100       188  
1551             if(UNIVERSAL::isa($field, 'Rose::HTML::Form::Field::Compound'))
1552 6 100 33     37 {
      66        
1553             $field = $field->field($rest);
1554 2         36 return ($self->{'field_cache'}{$name} = $field) if($field);
1555 2         10 }
1556              
1557             my($parent_form, $local_name) = $self->find_parent_form($name);
1558              
1559 77         142 return undef unless($parent_form);
1560              
1561             return $self->{'field_cache'}{$name} = $parent_form->field($local_name, @_);
1562             }
1563              
1564 1638     1638 1 2321 {
1565             my($self) = shift;
1566 1638 100       2743  
1567             if(@_)
1568 257         651 {
1569             $self->delete_fields;
1570 257         784 $self->add_fields(@_);
1571 8     8   54 }
  8         16  
  8         20607  
1572 257 100       658  
1573 257         891 if(my $fields = $self->{'field_list'})
1574 257         677 {
1575 257         1147 return wantarray ? @$fields : $fields;
1576             }
1577              
1578 1381   66     5715 my $fields = $self->{'fields'};
1579             my $fields_by_name = $self->{'fields_by_name'};
1580              
1581             $self->{'field_list'} =
1582             [
1583 135     135 1 200 grep { defined }
1584 135 50       150 map
  135         499  
1585             {
1586             if(/$FF_SEPARATOR_RE([^$FF_SEPARATOR_RE]+)/o)
1587             {
1588             $self->field($_) || $fields->{$1} || $fields_by_name->{$1};
1589 8     8 1 1056 }
1590 8         34 else
1591 8         30 {
1592 8         252 $fields->{$_} || $fields_by_name->{$_} || $self->field($_);
1593 8         38 }
1594 8         29 }
1595 8         32 $self->field_monikers
1596             ];
1597              
1598             return wantarray ? @{$self->{'field_list'}} : $self->{'field_list'};
1599             }
1600 2     2 1 7  
1601             {
1602 2 50       14 my($self) = shift;
1603              
1604 2         9 my @fields = sort { $a->rank <=> $b->rank } $self->local_fields;
1605              
1606 2         5 foreach my $form ($self->forms)
1607 2         5 {
1608 2   33     10 push(@fields, $form->fields_depth_first);
1609             }
1610              
1611             return wantarray ? @fields : \@fields;
1612             }
1613 3114     3114 1 15367  
1614             {
1615 3114 100       7189 my($self) = shift;
1616              
1617 2485         2670 if(my $names = $self->{'field_monikers'})
1618             {
1619             return wantarray ? @$names : $names;
1620 2485 100       4276 }
1621              
1622 1587         2799 my @info;
1623              
1624             $self->_find_field_info($self, \@info);
1625              
1626 898         1277 $self->{'field_monikers'} =
1627 898         1209 [ map { $_->[2] } sort { $self->compare_forms($a->[0], $b->[0]) || $self->compare_fields($a->[1], $b->[1]) } @info ];
1628 898         1316  
1629             return wantarray ? @{$self->{'field_monikers'}} : $self->{'field_monikers'};
1630 898 100       1794 }
1631              
1632 17         58  
1633 17 50       94 {
1634             my($self, $form, $list) = @_;
1635              
1636 881         1375 while(my($name, $field) = each %{$form->{'fields'}})
1637             {
1638 881 50       1533 push(@$list, [ $form, $field, $field->fq_moniker ]);
1639             }
1640 881         1450  
1641             foreach my $sub_form ($form->forms)
1642             {
1643             $form->_find_field_info($sub_form, $list);
1644             }
1645 906     906 1 2097 }
1646              
1647 906 100       1699 {
1648             my($self, $name) = @_;
1649 2         7  
1650 2         15 # Non-hierarchical name
1651             if(index($name, FF_SEPARATOR) < 0)
1652             {
1653 906 100       1791 return $self->local_form($name) ? ($self, $name) : undef;
1654             }
1655 660 100       1813  
1656             my $parent_form;
1657              
1658 246         400 while($name =~ s/^([^$FF_SEPARATOR_RE]+)$FF_SEPARATOR_RE//o)
1659 246         385 {
1660             my $parent_name = $1;
1661             last if($parent_form = $self->local_form($parent_name));
1662             }
1663 1605         2366  
1664             unless(defined $parent_form)
1665             {
1666 246 100       679 # Maybe this form ($self) is the parent?
  1605         3583  
1667             return ($self, $name) if($self->local_field($name));
1668 610 0 33     1036 return undef;
1669             }
1670              
1671             return wantarray ? ($parent_form, $name) : $parent_form;
1672 995 50 66     2067 }
1673              
1674             {
1675             my($self, $name) = @_;
1676              
1677             # Non-hierarchical name
1678 246 50       632 if(index($name, FF_SEPARATOR) < 0)
  246         725  
1679             {
1680             return wantarray ? ($self, $name) : $self;
1681             }
1682              
1683 52     52 1 114 my($parent_form, $local_name);
1684              
1685 52         88 while($name =~ s/^(.+)$FF_SEPARATOR_RE([^$FF_SEPARATOR_RE]+)$//o)
  19         67  
1686             {
1687 52         86 $local_name = $2;
1688             last if($parent_form = $self->form($1));
1689 42         92 }
1690              
1691             return wantarray ? ($parent_form, $local_name) : $parent_form;
1692 52 50       111 }
1693              
1694             {
1695             my($self) = shift;
1696              
1697 267     267 1 1434 return $self->form_name unless($self->parent_form);
1698              
1699 267 100       587 my @parts;
1700             my $form = $self;
1701 25 100       214  
1702             while(my $parent_form = $form->parent_form)
1703             {
1704 242         348 unshift(@parts, $form->form_name);
1705             $form = $parent_form;
1706 242         748 }
1707              
1708             return @parts ? join(FF_SEPARATOR, @parts) : '';
1709 242 50       809 }
  1598         3442  
  3953         7211  
1710              
1711 242 50       755 {
  242         1062  
1712             my($self) = shift;
1713              
1714 13     13 1 65 return undef unless($self->parent_form);
1715              
1716             my @context;
1717             my $form = $self;
1718 547     547   891  
1719             for(;;)
1720 547         996 {
  2145         5286  
1721             last unless($form->parent_form);
1722 1598         3316 unshift(@context, $form->form_name);
1723             $form = $form->parent_form;
1724             }
1725 547         1174  
1726             return join(FF_SEPARATOR, @context) . FF_SEPARATOR;
1727 305         548 }
1728              
1729             {
1730             my($self, $name) = @_;
1731             return $self->{'forms'}{$name} if(exists $self->{'forms'}{$name});
1732             return undef;
1733 1241     1241 0 1870 }
1734              
1735             {
1736 1241 100       2385 my($self, $name) = (shift, shift);
1737              
1738 277 50       552 # Set form
1739             if(@_)
1740             {
1741 964         1005 my $form = shift;
1742             $self->delete_form($name);
1743 964         3439 return $self->add_form($name => $form);
1744             }
1745 1335         2273  
1746 1335 100       2015 # Local form?
1747             if(my $form = $self->local_form($name))
1748             {
1749 964 100       1634 return $form;
1750             }
1751              
1752 51 100       99 # Look up nested form
1753 21         42 my($parent_form, $local_name) = $self->find_parent_form($name);
1754             return undef unless(defined $parent_form);
1755             return $parent_form->form($local_name);
1756 913 50       2047 }
1757              
1758             {
1759             my($self, %args) = @_;
1760              
1761 2     2 0 7 my $xhtml = delete $args{'_xhtml'} ? 'xhtml' : 'html';
1762             my $xhtml_field = "${xhtml}_field";
1763             my $xhtml_label = "${xhtml}_label";
1764 2 50       6  
1765             my $max_button_depth =
1766 0 0       0 exists $args{'max_button_depth'} ? $args{'max_button_depth'} : 1;
1767              
1768             $args{'class'} = defined $args{'class'} ?
1769 2         5 "$args{'class'} form" : 'form';
1770              
1771 2         33 $args{'tr'} ||= {};
1772             $args{'td'} ||= {};
1773 2         7  
1774 2 50       8 $args{'table'}{'class'} = defined $args{'table'}{'class'} ?
1775             "$args{'table'}{'class'} form" :
1776             defined $args{'class'} ? $args{'class'} : undef;
1777 2 50       9  
1778             $args{'tr'}{'class'} = defined $args{'tr'}{'class'} ?
1779             "$args{'tr'}{'class'} field" : 'field';
1780              
1781             my $html = join('', map { $_->$xhtml() } $self->pre_children);
1782 6502     6502 0 7576  
1783             $html .= join("\n", map { $_->$xhtml_field() }
1784 6502 100       9540 grep { $_->isa('Rose::HTML::Form::Field::Hidden') } $self->fields);
1785              
1786 2145         2501 $html .= "\n\n" if($html);
1787 2145         2510  
1788             $html .= '<table' . Rose::HTML::Util::html_attrs_string($args{'table'}) . ">\n";
1789 2145         3540  
1790             my $form_start = "start_$xhtml";
1791 4037         5723 my $form_end = "end_$xhtml";
1792 4037         7690  
1793             my $i = 1;
1794              
1795 2145 50       7112 my @buttons;
1796              
1797             foreach my $field (grep { !$_->isa('Rose::HTML::Form::Field::Hidden') } $self->fields_depth_first)
1798             {
1799             if($field->is_button)
1800 126     126 0 189 {
1801             next if($field->field_depth > $max_button_depth);
1802 126 100       257  
1803             if($field->field_depth == 1)
1804 18         25 {
1805 18         27 push(@buttons, $field);
1806             next;
1807 18         21 }
1808             }
1809 45 100       71  
1810 27         47 if($field->isa('Rose::HTML::Form::Field::File'))
1811 27         54 {
1812             $form_start = "start_multipart_$xhtml";
1813             }
1814 18         71  
1815             my $odd_even = $i++ % 2 ? 'odd' : 'even';
1816              
1817             local $args{'tr'}{'class'} = "field-$odd_even";
1818             local $args{'td'}{'class'} = $args{'td'}{'class'} ? "$args{'td'}{'class'} label" : 'label';
1819 2172     2172 1 3138  
1820 2172 100       4918 my $label = $field->$xhtml_label();
1821 1059         2922  
1822             unless($label)
1823             {
1824             my $name = $field->name;
1825              
1826 561     561 1 13943 for($name)
1827             {
1828             tr[_.][ ];
1829 561 100       1141 s/\b(\w)/\u$1/g;
1830             }
1831 1         9  
1832 1         8 $label = Rose::HTML::Label->new(contents => Rose::HTML::Util::escape_html($name));
1833 1         6  
1834             if($field->html_attr_exists('id'))
1835             {
1836             $label->for($field->html_attr('id'));
1837 560 100       1233 }
1838              
1839 200         847 $label = $label->$xhtml();
1840             }
1841              
1842             if($field->is_button)
1843 360         846 {
1844 360 100       1331 local $args{'td'}{'colspan'} = 2;
1845 62         134 $html .= '<tr' . Rose::HTML::Util::html_attrs_string($args{'tr'}) . ">\n" .
1846             '<td' . Rose::HTML::Util::html_attrs_string($args{'td'}) . '>' .
1847             $field->$xhtml_field . "</td>\n</tr>\n";
1848             }
1849             else
1850 5     5   16 {
1851             $html .= '<tr' . Rose::HTML::Util::html_attrs_string($args{'tr'}) . ">\n" .
1852 5 50       14 '<td' . Rose::HTML::Util::html_attrs_string($args{'td'}) . ">$label</td>\n";
1853 5         11  
1854 5         9 $args{'td'}{'class'} =~ s/(?:^| )label$//;
1855             $args{'td'}{'class'} = $args{'td'}{'class'} ? "$args{'td'}{'class'} field" : 'field';
1856              
1857 5 50       13 $html .= '<td' . Rose::HTML::Util::html_attrs_string($args{'td'}) . '>' .
1858             $field->$xhtml() .
1859 5 50       12 "</td>\n</tr>\n";
1860             }
1861             }
1862 5   50     24  
1863 5   50     19 if(@buttons)
1864             {
1865             my $odd_even = $i++ % 2 ? 'odd' : 'even';
1866              
1867 5 50       22 local $args{'tr'}{'class'} = "field-$odd_even buttons";
    50          
1868             local $args{'td'}{'class'} = $args{'td'}{'class'} ? "$args{'td'}{'class'} label" : 'label';
1869 5 50       14  
1870             local $args{'td'}{'colspan'} = 2;
1871              
1872 5         22 $html .= '<tr' . Rose::HTML::Util::html_attrs_string($args{'tr'}) . ">\n" .
  2         8  
1873             '<td' . Rose::HTML::Util::html_attrs_string($args{'td'}) . '>' .
1874 0         0 join(' ', map { $_->$xhtml_field() } @buttons) .
1875 5         15 "</td>\n</tr>\n";
  10         41  
1876             }
1877 5 100       13  
1878             $html .= "</table>\n\n" . join('', map { $_->$xhtml() } $self->post_children);
1879 5         17  
1880             $html .= "\n\n" unless($html =~ /\n\n\z/);
1881 5         204  
1882 5         10 return $self->$form_start() . "\n\n$html" . $self->$form_end();
1883             }
1884 5         8  
1885              
1886 5         5 {
1887             my($self) = shift;
1888 5         15 Scalar::Util::weaken($self->{'app'} = shift) if(@_);
  10         35  
1889             return $self->{'app'};
1890 10 50       27 }
1891              
1892 0 0       0 {
1893             my($self) = shift;
1894 0 0       0 Scalar::Util::weaken($self->{'app_form'} = shift) if(@_);
1895             return $self->{'app_form'};
1896 0         0 }
1897 0         0  
1898             our $AUTOLOAD;
1899              
1900             {
1901 10 50       49 my($self) = $_[0];
1902              
1903 0         0 my $class = ref($self) or croak "$self is not an object";
1904              
1905             my $delegate = $class->delegate_to_subforms;
1906 10 100       24  
1907             unless($delegate)
1908 10         29 {
1909 10 50       24 goto &Rose::HTML::Object::AUTOLOAD;
1910             }
1911 10         68  
1912             my $method = $AUTOLOAD;
1913 10 50       18 $method =~ s/.*://;
1914              
1915 10         26 my $to_form;
1916              
1917 10         20 foreach my $form ($self->forms)
1918             {
1919 10         15 if($form->can($method))
1920 10         82 {
1921             $to_form = $form;
1922             last;
1923 10         30 }
1924             }
1925 10 50       25  
1926             unless($to_form)
1927 0         0 {
1928             $Rose::HTML::Object::AUTOLOAD = $AUTOLOAD;
1929             goto &Rose::HTML::Object::AUTOLOAD;
1930 10         27 }
1931              
1932             if($delegate eq 'compile')
1933 10 50       47 {
1934             my $form_name = $to_form->form_name;
1935 0         0  
1936             no strict 'refs';
1937 0         0 *$AUTOLOAD = sub { shift->form($form_name)->$method(@_) };
1938             ${$class . '::__AUTODELEGATED'}{$method} = 1;
1939             goto &$AUTOLOAD;
1940             }
1941             elsif($delegate eq 'runtime')
1942             {
1943 10         31 $to_form->$method(@_);
1944             }
1945 10         337  
1946 10 50       26 $Rose::HTML::Object::AUTOLOAD = $AUTOLOAD;
1947             goto &Rose::HTML::Object::AUTOLOAD;
1948 10         25 }
1949              
1950             if(__PACKAGE__->localizer->auto_load_messages)
1951             {
1952             __PACKAGE__->localizer->load_all_messages;
1953             }
1954 5 50       11  
1955             use utf8; # The __DATA__ section contains UTF-8 text
1956 0 0       0  
1957             1;
1958 0         0  
1959 0 0       0 [% LOCALE en %]
1960              
1961 0         0 FORM_HAS_ERRORS = "One or more fields have errors."
1962              
1963             [% LOCALE de %]
1964              
1965 0         0 # oder "Es sind Fehler aufgetreten."
  0         0  
1966             FORM_HAS_ERRORS = "Ein oder mehrere Felder sind fehlerhaft."
1967              
1968             [% LOCALE fr %]
1969 5         18  
  2         6  
1970             FORM_HAS_ERRORS = "Erreurs dans un ou plusieurs champs."
1971 5 100       22  
1972             [% LOCALE bg %]
1973 5         15  
1974             FORM_HAS_ERRORS = "Има грешка в поне едно поле."
1975              
1976 0     0 0 0 __END__
1977 5     5 0 17  
1978             =head1 NAME
1979              
1980             Rose::HTML::Form - HTML form base class.
1981 0     0 1 0  
1982 0 0       0 =head1 SYNOPSIS
1983 0         0  
1984             package PersonForm;
1985              
1986             use base 'Rose::HTML::Form';
1987              
1988 0     0 0 0 use Person;
1989 0 0       0  
1990 0         0 sub build_form
1991             {
1992             my($self) = shift;
1993              
1994             $self->add_fields
1995             (
1996             name => { type => 'text', size => 25, required => 1 },
1997 3     3   3302 email => { type => 'email', size => 50, required => 1 },
1998             phone => { type => 'phone' },
1999 3 50       13 );
2000             }
2001 3         14  
2002             sub validate
2003 3 50       62 {
2004             my($self) = shift;
2005 0         0  
2006             # Base class will validate individual fields in isolation,
2007             # confirming that all required fields are filled in, and that
2008 3         6 # the email address and phone number are formatted correctly.
2009 3         17 my $ok = $self->SUPER::validate(@_);
2010             return $ok unless($ok);
2011 3         5  
2012             # Inter-field validation goes here
2013 3         9 if($self->field_value('name') ne 'John Doe' &&
2014             $self->field_value('phone') =~ /^555/)
2015 3 100       113 {
2016             $self->error('Only John Doe can have a 555 phone number.');
2017 2         4 return 0;
2018 2         3 }
2019              
2020             return 1;
2021             }
2022 3 100       11  
2023             sub init_with_person # give a friendlier name to a base-class method
2024 1         3 {
2025 1         5 my($self, $person) = @_;
2026             $self->init_with_object($person);
2027             }
2028 2 50       6  
    0          
2029             sub person_from_form
2030 2         6 {
2031             my($self) = shift;
2032 8     8   58  
  8         17  
  8         1104  
2033 2     2   14 # Base class method does most of the work
  2         8  
2034 2         5 my $person = $self->object_from_form(class => 'Person');
  2         22  
2035 2         9  
2036             # Now fill in the non-obvious details...
2037             # e.g., set alt phone to be the same as the regular phone
2038             $person->alt_phone($self->field_value('phone'));
2039 0            
2040             return $person;
2041             }
2042 0            
2043 0           ...
2044              
2045             #
2046             # Sample usage in a hypothetical web application
2047             #
2048              
2049             $form = PersonForm->new;
2050              
2051 8     8   2530 if(...)
  8         74  
  8         39  
2052             {
2053             # Get query parameters in a hash ref and pass to the form
2054             my $params = MyWebServer->get_query_params();
2055             $form->params($params);
2056              
2057             # ...or initialize form params from a CGI object
2058             # $form->params_from_cgi($cgi); # $cgi "isa" CGI
2059              
2060             # ...or initialize params from an Apache request object
2061             # (mod_perl 1 and 2 both supported)
2062             # $form->params_from_apache($r);
2063              
2064             # Initialize the fields based on params
2065             $form->init_fields();
2066              
2067             unless($form->validate)
2068             {
2069             return error_page(error => $form->error);
2070             }
2071              
2072             $person = $form->person_from_form; # $person is a Person object
2073              
2074             do_something_with($person);
2075             ...
2076             }
2077             else
2078             {
2079             $person = ...; # Get or create a Person object somehow
2080              
2081             # Initialize the form with the Person object
2082             $form->init_with_person($person);
2083              
2084             # Pass the initialized form object to the template
2085             display_page(form => $form);
2086             }
2087             ...
2088              
2089             =head1 DESCRIPTION
2090              
2091             L<Rose::HTML::Form> is more than just an object representation of the E<lt>formE<gt> HTML tag. It is meant to be a base class for custom form classes that can be initialized with and return "rich" values such as objects, or collections of objects.
2092              
2093             Building up a reusable library of form classes is extremely helpful when building large web applications with forms that may appear in many different places. Similar forms can inherit from a common subclass, and forms may be nested.
2094              
2095             This class inherits from, and follows the conventions of, L<Rose::HTML::Object>. Inherited methods that are not overridden will not be documented a second time here. See the L<Rose::HTML::Object> documentation for more information.
2096              
2097             =head1 OVERVIEW
2098              
2099             L<Rose::HTML::Form> objects are meant to encapsulate an entire HTML form, including all fields within the form. While individual fields may be queried and manipulated, the intended purpose of this class is to treat the form as a "black box" as much as possible.
2100              
2101             For example, instead of asking a form object for the values of the "name", "email", and "phone" fields, the user would ask the form object to return a new "Person" object that encapsulates those values.
2102              
2103             Form objects should also accept initialization through the same kinds of objects that they return. Subclasses are encouraged to create methods such as (to use the example described above) C<init_with_person()> and C<person_from_form()> in order to do this. The generic methods L<init_with_object()|/init_with_object> and L<object_from_form()|/object_from_form> are meant to ease the implementation of such custom methods.
2104              
2105             Form objects can also take input through a hash. Each hash key correspond to a field (or subfield) name, and each value is either a scalar or a reference to an array of scalars (for multiple-value fields). This hash of parameters can be queried and manipulated before finally calling L<init_fields()|/init_fields> in order to initialize the fields based on the current state of the parameters.
2106              
2107             Compound fields (fields consisting of more than one HTML field, such as a month/day/year date field with separate text fields for each element of the date) may be "addressed" by hash arguments using both top-level names (e.g., "birthday") or by subfield names (e.g., "birthday.month", "birthday.day", "birthday.year"). If the top-level name exists in the hash, then subfield names are ignored. See L<Rose::HTML::Form::Field::Compound> for more information on compound fields.
2108              
2109             Each form has a list of field objects. Each field object is stored under a name, which may or may not be the same as the field name, which may or may not be the same as the "name" HTML attribute for any of the HTML tags that make up that field.
2110              
2111             Forms are validated by calling L<validate()|Rose::HTML::Form::Field/validate> on each field object. If any individual field does not validate, then the form is invalid. Inter-field validation is the responsibility of the form object.
2112              
2113             =head1 HIERARCHY
2114              
2115             Though L<Rose::HTML::Form> objects may have L<children|Rose::HTML::Object/children> just like any other L<Rose::HTML::Object>-derived object, the L<fields|/fields> that make up the form are treated like "immutable children" in that they can never be removed using the standard child-related APIs. Instead, the fields exist in the middle of any other children.
2116              
2117             L<Pushing|Rose::HTML::Object/push_children> a child adds it after the list of fields. L<Unshifting|Rose::HTML::Object/unshift_children> a child adds it before the list of fields. L<Popping|Rose::HTML::Object/pop_children> or L<shifting|Rose::HTML::Object/shift_children> children will pull children through, past the fields, to exit the list of children at either end. In other words, children manipulated using the child object APIs will "flow around" the list of fields.
2118              
2119             If a particular field is a group of sibling HTML elements with no real parent HTML element (e.g., a L<radio button group|Rose::HTML::Form::Field::RadioButtonGroup>), then the individual sibling items will be flattened out into the list returned by the L<children|Rose::HTML::Object/children> method.
2120              
2121             If, on the other hand, a field has a true parent/child relationship (e.g., a L<select box|Rose::HTML::Form::Field::SelectBox> which contains zero or more L<options|Rose::HTML::Form::Field::Option>) then the items it contains are not flattened by the L<children|Rose::HTML::Object/children> method.
2122              
2123             For example, if a form has three fields, a text field, a checkbox group with three checkboxes, and a select box with three options, then the L<children|Rose::HTML::Object/children> method will return five objects: the L<text field|Rose::HTML::Form::Field::Text> object, the three L<checkboxes|Rose::HTML::Form::Field::Checkbox> objects, and a L<select box|Rose::HTML::Form::Field::SelectBox> object.
2124              
2125             See the L<hierarchy section|Rose::HTML::Form::Field/HIERARCHY> of the L<Rose::HTML::Form::Field> documentation for more information about how fields made up of multiple HTML tags are treated with respect to parent/child relationships.
2126              
2127             Finally, note that L<nested forms|/"NESTED FORMS"> do not affect the parent/child hierarchy presented by the child-related methods inherited from L<Rose::HTML::Object> since the fields contained in nested forms are flattened out into the field list of parent form, as described in the next section.
2128              
2129             =head1 NESTED FORMS
2130              
2131             Each form can have zero or more fields as well as zero or more sub-forms. Since E<lt>formE<gt> HTML tags cannot be nested, this nesting of form objects appears "flattened" in the external interfaces such as HTML generation or field addressing.
2132              
2133             Here's a simple example of a nested form made up of a C<PersonForm> and an C<AddressForm>. (Assume C<PersonForm> is constructed as per the L<synopsis|/SYNOPSIS> above, and C<AddressForm> is similar, with street, city, state, and zip code fields.)
2134              
2135             package PersonAddressForm;
2136              
2137             use PersonForm;
2138             use AddressForm;
2139              
2140             sub build_form
2141             {
2142             my($self) = shift;
2143              
2144             $self->add_forms
2145             (
2146             person => PersonForm->new,
2147             address => AddressForm->new,
2148             );
2149             }
2150              
2151             Each sub-form is given a name. Sub-field addressing incorporates that name in much the same way as L<compound field|Rose::HTML::Form::Field::Compound> addressing, with dots (".") used to delimit the hierarchy. Here are two different ways to get at the person's email field.
2152              
2153             $form = PersonAddressForm->new;
2154              
2155             # These are equivalent
2156             $email_field = $form->field('person.email');
2157             $email_field = $form->form('person')->field('email');
2158              
2159             Methods on the sub-forms maybe accessed in a similar manner.
2160              
2161             $person = $form->form('person')->person_from_form();
2162              
2163             By default, methods are delegated to sub-forms automatically, so this works too.
2164              
2165             $person = $form->person_from_form();
2166              
2167             (See the L<delegate_to_subforms()|/delegate_to_subforms> method to learn how to alter this behavior.)
2168              
2169             Nested forms may have their own fields as well, and the nesting may continue to an arbitrary depth. Here's a form that contains a C<PersonAddressForm> as well as two fields of its own.
2170              
2171             package PersonAddressPetsForm;
2172              
2173             use PersonAddressForm;
2174              
2175             sub build_form
2176             {
2177             my($self) = shift;
2178              
2179             $self->add_form(pa => PersonAddressForm->new);
2180              
2181             $self->add_fields
2182             (
2183             dog => { type => 'text', size => 30 },
2184             cat => { type => 'text', size => 30 },
2185             );
2186             }
2187              
2188             Sub-form and field addressing works as expected. Here are several equivalent ways to get at the person's email field.
2189              
2190             $form = PersonAddressPetsForm->new;
2191              
2192             # These are all equivalent
2193             $email_field = $form->field('pa.person.email');
2194             $email_field = $form->form('pa.person')->field('email');
2195             $email_field = $form->form('pa')->form('person')->field('email');
2196              
2197             Sub-form method calls and delegation also works as expected.
2198              
2199             # Call method on the PersonForm, two different ways
2200             $person = $form->form('pa')->form('person')->person_from_form();
2201             $person = $form->form('pa.person')->person_from_form();
2202              
2203             # Rely on delegation instead
2204             $person = $form->form('pa')->person_from_form();
2205             $person = $form->person_from_form();
2206              
2207             Nested forms are a great way to build on top of past work. When combined with traditional subclassing, form generation can be entirely cleansed of duplicated code.
2208              
2209             =head1 HTML ATTRIBUTES
2210              
2211             Valid attributes:
2212              
2213             accept
2214             accept-charset
2215             accesskey
2216             action
2217             class
2218             dir
2219             enctype
2220             id
2221             lang
2222             method
2223             name
2224             onblur
2225             onclick
2226             ondblclick
2227             onfocus
2228             onkeydown
2229             onkeypress
2230             onkeyup
2231             onmousedown
2232             onmousemove
2233             onmouseout
2234             onmouseover
2235             onmouseup
2236             onreset
2237             onsubmit
2238             style
2239             tabindex
2240             target
2241             title
2242             value
2243             xml:lang
2244              
2245             Required attributes (default values in parentheses):
2246              
2247             action
2248             enctype (application/x-www-form-urlencoded)
2249             method (get)
2250              
2251             =head1 CLASS METHODS
2252              
2253             =over 4
2254              
2255             =item B<default_recursive_init_fields [BOOL]>
2256              
2257             Get or set a boolean value that determines the default value of the L<recursive_init_fields|/recursive_init_fields> object attribute. The default value is false.
2258              
2259             =item B<delegate_to_subforms [SETTING]>
2260              
2261             Get or set the value that determines how (or if) forms of this class delegate unresolved method calls to L<sub-forms|/"NESTED FORMS">. If a method is called on a form of this class, and that method does not exist in this class or any other class in its inheritance hierarchy, then the method may optionally be delegated to a L<sub-forms|/"NESTED FORMS">. Valid values for SETTING are:
2262              
2263             =over 4
2264              
2265             =item "B<0>"
2266              
2267             A value of "0" (or undef or any other false value) means that no sub-form delegation will be attempted.
2268              
2269             =item "B<1>"
2270              
2271             A value of "1" means the same thing as a value of "runtime" (see below).
2272              
2273             =item "B<compile>"
2274              
2275             For each unresolved method call, each sub-form is is considered in the order that they are returned from the L<forms|/forms> method until one is found that L<can|perlobj/can> handle this method. If one is found, then a new proxy method is added to this class that calls the requested method on the sub-form, passing all arguments unmodified. That proxy method is then called.
2276              
2277             Subsequent invocations of this method will no longer trigger the search process. Instead, they will be handled by the newly-compiled proxy method. This is more efficient than repeating the sub-form search each time, but it also means that a change in the list of sub-forms could render the newly compiled method useless (e.g., if the sub-form it delegates to is removed).
2278              
2279             If no sub-form can handle the method, then a fatal "unknown method" error occurs.
2280              
2281             =item "B<runtime>"
2282              
2283             For each unresolved method call, each sub-form is is considered in the order that they are returned from the L<forms|/forms> method until one is found that L<can|perlobj/can> handle this method. If one is found, then the method is called on that sub-form, passing all arguments unmodified.
2284              
2285             Subsequent invocations of this method will trigger the same search process, again looking for a a sub-form that can handle it. This is less efficient than compiling a new proxy method as described in the documentation for the "compile" setting above, but it does mean that any changes in the list of sub-forms will be handled correctly.
2286              
2287             If no sub-form can handle the method, then a fatal "unknown method" error occurs.
2288              
2289             =back
2290              
2291             The default value for SETTING is B<compile>. See the L<nested forms|/"NESTED FORMS"> section for some examples of sub-form delegation.
2292              
2293             =item B<default_trim_xy_params [BOOL]>
2294              
2295             Get or set a boolean value that is used as the default value of the L<trim_xy_params|/trim_xy_params> object attribute. The default value is true.
2296              
2297             =back
2298              
2299             =head1 CONSTRUCTOR
2300              
2301             =over 4
2302              
2303             =item B<new PARAMS>
2304              
2305             Constructs a new L<Rose::HTML::Form> object based on PARAMS, where PARAMS are name/value pairs. Any object method is a valid parameter name.
2306              
2307             =back
2308              
2309             =head1 OBJECT METHODS
2310              
2311             =over 4
2312              
2313             =item B<add_field ARGS>
2314              
2315             Convenience alias for L<add_fields()|/add_fields>.
2316              
2317             =item B<add_fields ARGS>
2318              
2319             Add the fields specified by ARGS to the list of fields contained in this form. ARGS may be a list or a reference to an array. Valid formats for elements of ARGS are:
2320              
2321             =over 4
2322              
2323             =item B<Field objects>
2324              
2325             If an argument is "isa" L<Rose::HTML::Form::Field>, then it is added to the list of fields, stored under the name returned by the field's L<name|Rose::HTML::Form::Field/name> method.
2326              
2327             =item B<Field name/type pairs>
2328              
2329             A pair of simple scalars is taken as a field name and type. The class that corresponds to the specified field type is determined by calling the L<field_type_class|/field_type_class> method. Then a new object of that class is constructed and added to the form.
2330              
2331             =item B<Field name/hashref pairs>
2332              
2333             A simple scalar followed by a reference to a hash it taken as a field name and a collection of object attributes. The referenced hash must contain a value for the C<type> key. The field class that corresponds to the specified field type is determined by calling the L<field_type_class|/field_type_class> method. Then a new object of that class is constructed, with the remaining key/value pairs in the hash are passed to the constructor. The completed field object is then added to the form.
2334              
2335             =item B<Field name/object pairs>
2336              
2337             A simple scalar followed by an object that "isa" L<Rose::HTML::Form::Field> is stored as-is, under the specified name.
2338              
2339             =back
2340              
2341             Each field's L<parent_form|Rose::HTML::Form::Field/parent_form> is set to the form object. If the field's L<rank|Rose::HTML::Form::Field/rank> is undefined, it's set to the value of the form's L<field_rank_counter|/field_rank_counter> attribute and the rank counter is incremented.
2342              
2343             Adding a field with the same name as an existing L<sub-form|/"NESTED FORMS"> will cause a fatal error.
2344              
2345             Examples:
2346              
2347             # Name/hashref pairs
2348             $form->add_fields(name => { type => 'text', size => 20 },
2349             email => { type => 'email', size => 30 });
2350              
2351             # Name/type pairs
2352             $form->add_fields(name => 'text',
2353             email => 'email');
2354              
2355             $name_field =
2356             Rose::HTML::Form::Field::Text->new(name => 'name',
2357             size => 25);
2358              
2359             $email_field =
2360             Rose::HTML::Form::Field::Text->new(name => 'email',
2361             size => 50);
2362              
2363             # Object arguments
2364             $form->add_fields($name_field, $email_field);
2365              
2366             # Name/object pairs
2367             $form->add_fields(name => $name_field,
2368             email => $email_field);
2369              
2370             # Mixed
2371             $form->add_fields($name_field,
2372             email => $email_field,
2373             nick => { type => 'text', size => 15 },
2374             age => 'text');
2375              
2376             =item B<add_field_type_classes [MAP]>
2377              
2378             Add entries to the L<field_type_classes|/field_type_classes> hash that maps field type strings to the names of the L<Rose::HTML::Form::Field>-derived classes. Example:
2379              
2380             My::HTML::Form->add_field_type_classes
2381             (
2382             nick => 'My::HTML::Form::Field::Nickname',
2383             age => 'My::HTML::Form::Field::Age',
2384             ...
2385             );
2386              
2387             This method is an alias for the L<add_object_type_classes|Rose::HTML::Object/add_object_type_classes> method inherited from L<Rose::HTML::Object>. It is an L<inherited hash|Rose::Class::MakeMethods::Generic/inherited_hash> representing the union of the hashes of all superclasses, minus any keys that are explicitly L<deleted|/delete_field_type_class> in the current class.
2388              
2389             =item B<add_form ARGS>
2390              
2391             This is an alias for the L<add_forms()|/add_forms> method.
2392              
2393             =item B<add_forms ARGS>
2394              
2395             Add the forms specified by ARGS to the list of sub-forms contained in this form. See the L<nested forms|/"NESTED FORMS"> section for more information.
2396              
2397             Valid formats for elements of ARGS are:
2398              
2399             =over 4
2400              
2401             =item B<Form objects>
2402              
2403             If an argument is "isa" L<Rose::HTML::Form>, then it is added to the list of forms, stored under the name returned by the form's L<form_name|/form_name> method. Example:
2404              
2405             $a_form = Rose::HTML::Form->new(...);
2406             $b_form = Rose::HTML::Form->new(...);
2407              
2408             # Object arguments
2409             $form->add_forms($a_form, $b_form);
2410              
2411             =item B<Form name/object pairs>
2412              
2413             A simple scalar followed by an object that "isa" L<Rose::HTML::Form> has its L<form_name|/form_name> set to the specified name and then is stored under that name.
2414              
2415             If the name contains any dots (".") it will be taken as a hierarchical name and the form will be added to the specified sub-form under an unqualified name consisting of the final part of the name.
2416              
2417             Examples:
2418              
2419             $a_form = Rose::HTML::Form->new(...);
2420             $b_form = Rose::HTML::Form->new(...);
2421              
2422             # Name/object pairs
2423             $form->add_forms(a => $a_form, b => $b_form);
2424              
2425             # Mixed
2426             $form->add_forms($a_form, b => $b_form);
2427              
2428             # Set nested form from the top-level
2429             $w_form = Rose::HTML::Form->new(...);
2430             $x_form = Rose::HTML::Form->new(...);
2431             $y_form = Rose::HTML::Form->new(...);
2432             $z_form = Rose::HTML::Form->new(...);
2433              
2434             $w_form->add_form('x' => $x_form);
2435             $x_form->add_form('y' => $y_form);
2436              
2437             # Add $z_form to $w_form->form('x')->form('y') under the name 'z'
2438             $w_form->add_form('x.y.z' => $z_form);
2439              
2440             =item B<Form name/hashref pairs>
2441              
2442             A simple scalar followed by a reference to a hash containing a specification for a form. Currently, the only kind of form that can be specified this way is a L<repeatable form|Rose::HTML::Form::Repeatable>, in which case the hash reference is known as a "repeat spec". In order to be correctly detected as a repeat spec, the hash I<must> contain a key named C<repeatable>.
2443              
2444             The repeat spec is coerced into a set of name/value pairs that are passed to the L<Rose::HTML::Form::Repeatable> constructor call. The coercion exists to allow shorter, more friendly names to be used in the context of a repeat spec. These names are converted into the names of valid L<Rose::HTML::Form::Repeatable> object methods. The following coercion rules are applied to the repeat spec hash reference:
2445              
2446             =over 4
2447              
2448             =item * If the value of the C<repeatable> key is reference to a hash, the keys and values of that hash are folded into the repeat spec. Otherwise, if a key named C<default_count> does not exist in the repeat spec, then the value of the C<repeatable> key is used as the value of the L<default_count|Rose::HTML::Form::Repeatable/default_count> parameter.
2449              
2450             =item * The C<spec> and C<form_spec> parameters are aliases for the L<prototype_form_spec|Rose::HTML::Form::Repeatable/prototype_form_spec> parameter.
2451              
2452             =item * The C<class> and C<form_class> parameters are aliases for the L<prototype_form_class|Rose::HTML::Form::Repeatable/prototype_form_class> parameter.
2453              
2454             =item * The C<form> parameter is an alias for the L<prototype_form|Rose::HTML::Form::Repeatable/prototype_form> parameter.
2455              
2456             =back
2457              
2458             Here are some example name/hashref pairs suitable for passing as arguments to the L<add_forms|/add_forms> method:
2459              
2460             # Using a form class name
2461             emails =>
2462             {
2463             form_class => 'EmailForm',
2464             repeatable => 3, # Default count is 3.
2465             }
2466              
2467             # Using a form class name and form spec
2468             emails =>
2469             {
2470             form_class => 'EmailForm',
2471             form_spec => { empty_is_ok => 1 },
2472             repeatable => 3, # Default count is 3.
2473             }
2474              
2475             # Using a generic form class and form spec to specify the
2476             # contents of a repeated form "inline" in the repeat spec
2477             nicknames =>
2478             {
2479             form_class => 'My::HTML::Form',
2480             form_spec => { fields => [ nick => { type => 'text' } ] },
2481             repeatable => 3, # Default count is 3.
2482             }
2483              
2484             # Using a prototype object
2485             nicknames =>
2486             {
2487             form => NickNameForm->new,
2488             default_count => 0, # Explicitly set default count to 0.
2489             repeatable => 1, # This key must be present even though
2490             # the default count is set above.
2491             }
2492              
2493             =back
2494              
2495             Each form's L<parent_form|/parent_form> is set to the form object it was added to.
2496              
2497             Adding a form with the same name as an existing field will cause a fatal error.
2498              
2499             =item B<add_param_value NAME, VALUE>
2500              
2501             Add VALUE to the parameter named NAME. Example:
2502              
2503             $form->param(a => 1);
2504             print $form->param('a'); # 1
2505              
2506             $form->add_param_value(a => 2);
2507              
2508             print join(',', $form->param('a')); # 1,2
2509              
2510             =item B<app [OBJECT]>
2511              
2512             Get or set a L<weakened|Scalar::Util/weaken> reference to the application object that "owns" this form.
2513              
2514             =item B<add_repeatable_form ARGS>
2515              
2516             This method is an alias for the L<add_repeatable_forms()|/add_repeatable_forms> method.
2517              
2518             =item B<add_repeatable_forms ARGS>
2519              
2520             Add the repeatable forms specified by ARGS to the list of sub-forms contained in this form. This method takes arguments in the same format as the L<add_forms|/add_forms> method, except that all argument types are coerced into a form that will cause L<add_forms|/add_forms> to recognize it as a L<repeatable form|Rose::HTML::Form::Repeatable>. This is a convenient way to add repeatable forms without having to include the C<repeatable> key in your repeat spec. (See the documentation for the L<add_forms|/add_forms> method for more information.)
2521              
2522             Examples
2523              
2524             $form->add_repeatable_forms
2525             (
2526             # Object argument
2527             EmailForm->new(...),
2528              
2529             # Name/object pair
2530             colors => ColorForm->new(...),
2531              
2532             # Name/hashref pair. (Note: no "repeatable" key needed)
2533             nicknames =>
2534             {
2535             form => NickNameForm->new,
2536             default_count => 2,
2537             },
2538             );
2539              
2540             =item B<build_on_init [BOOL]>
2541              
2542             Get or set a boolean flag that indicates whether or not L<build_form()|/build_form> should be called from within the L<init()|Rose::Object/init> method. See L<build_form()|/build_form> for more information.
2543              
2544             =item B<build_form>
2545              
2546             This default implementation of this method is a no-op. It is meant to be overridden by subclasses. It is called at the end of the L<init()|Rose::Object/init> method if L<build_on_init()|/build_on_init> is true. (Remember that this class inherits from L<Rose::HTML::Object>, which inherits from L<Rose::Object>, which defines the L<init()|Rose::Object/init> method, which is called from the constructor. See the L<Rose::Object> documentation for more information.)
2547              
2548             If L<build_on_init()|/build_on_init> is false, then you must remember to call L<build_form()|/build_form> manually.
2549              
2550             Subclasses should populate the field list in their overridden versions of L<build_form()|/build_form>. Example:
2551              
2552             sub build_form
2553             {
2554             my($self) = shift;
2555              
2556             $self->add_fields
2557             (
2558             name => { type => 'text', size => 25, required => 1 },
2559             email => { type => 'email', size => 50, required => 1 },
2560             phone => { type => 'phone' },
2561             );
2562             }
2563              
2564             =item B<clear>
2565              
2566             Call L<clear()|Rose::HTML::Form::Field/clear> on each field object and set L<error()|Rose::HTML::Object/error> to undef.
2567              
2568             =item B<clear_fields>
2569              
2570             Call L<clear()|Rose::HTML::Form::Field/clear> on each field object.
2571              
2572             =item B<coalesce_hidden_fields [BOOL]>
2573              
2574             Get or set the boolean flag that controls how compound field values are encoded in hidden fields. If this flag is true, then each compound field is encoded as a single hidden field. If the flag is false (the default), then each subfield of a compound field will have its own hidden field.
2575              
2576             =item B<coalesce_query_string_params [BOOL]>
2577              
2578             Get or set the boolean flag that controls how compound field values are encoded in the query string. If this flag is true (the default), then compound fields are represented by a single query parameter. Otherwise, the subfields of each compound field appear as separate query parameters.
2579              
2580             =item B<compare_fields [FIELD1, FIELD2]>
2581              
2582             Compare two fields, returning 1 if FIELD1 should come before FIELD2, -1 if FIELD2 should come before FIELD1, or 0 if neither field should come before the other. This method is called from within the L<field_names|/field_names> method to determine the order of the fields in this form.
2583              
2584             The default implementation performs a string comparison on the L<name|Rose::HTML::Form::Field/name>s of the fields.
2585              
2586             =item B<compare_forms [FORM1, FORM2]>
2587              
2588             Compare two forms, returning 1 if FORM1 should come before FORM2, -1 if FORM2 should come before FORM1, or 0 if neither form should come before the other. This method is called from within the L<form_names|/form_names> and L<field_monikers|/field_monikers> methods to determine the order of the sub-forms nested within this form.
2589              
2590             The default implementation compares the L<rank|/rank> of the forms in numeric context.
2591              
2592             =item B<delete_field NAME>
2593              
2594             Delete the form stored under the name NAME. If NAME "isa" L<Rose::HTML::Form::Field>, then the L<name|Rose::HTML::Form::Field/name> method is called on it and the return value is used as NAME.
2595              
2596             =item B<delete_fields>
2597              
2598             Delete all fields, leaving the list of fields empty. The L<field_rank_counter|/field_rank_counter> is also reset to 1.
2599              
2600             =item B<delete_field_type_class TYPE>
2601              
2602             Delete the type/class L<mapping|/field_type_classes> entry for the field type TYPE.
2603              
2604             =item B<delete_form NAME>
2605              
2606             Delete the form stored under the name NAME. If NAME "isa" L<Rose::HTML::Form>, then the L<form_name|/form_name> method is called on it and the return value is used as NAME.
2607              
2608             =item B<delete_forms>
2609              
2610             Delete all sub-forms, leaving the list of sub-forms empty.
2611              
2612             =item B<delete_param NAME [, VALUES]>
2613              
2614             If just the NAME argument is passed, the parameter named NAME is deleted.
2615              
2616             If VALUES are also passed, then VALUES are deleted from the set of values held by the parameter name NAME. If only one value remains, then it is the new value for the NAME parameter (i.e., the value is no longer an array reference, but a scalar instead). If every value is deleted, then the NAME parameter is deleted as well. Example:
2617              
2618             $form->param(a => [ 1, 2, 3, 4 ]);
2619              
2620             $form->delete_param(a => 1);
2621             $vals = $form->param('a'); # [ 2, 3, 4 ]
2622              
2623             $form->delete_param(a => [ 2, 3 ]);
2624             $vals = $form->param('a'); # 4
2625              
2626             $form->delete_param(a => 4);
2627             $vals = $form->param('a'); # undef
2628             $form->param_exists('a'); # false
2629              
2630             =item B<delete_params>
2631              
2632             Delete all parameters.
2633              
2634             =item B<delete_repeatable_form NAME>
2635              
2636             Delete the repeatable form stored under the name NAME. If NAME "isa" L<Rose::HTML::Form>, then the L<form_name|/form_name> method is called on it and the return value is used as NAME.
2637              
2638             =item B<delete_repeatable_forms>
2639              
2640             Delete all repeatable sub-forms.
2641              
2642             =item B<empty_is_ok [BOOL]>
2643              
2644             Get or set a boolean value that indicates whether or not L<validate|/validate> will be allowed to return true if every L<field|/fields> in the form is empty, even if some of them are L<required|Rose::HTML::Form::Field/required>. The default value is false.
2645              
2646             =item B<end_html>
2647              
2648             Returns the HTML required to end the form.
2649              
2650             =item B<end_xhtml>
2651              
2652             Returns the XHTML required to end the form.
2653              
2654             =item B<end_multipart_html>
2655              
2656             Returns the HTML required to end a multipart form.
2657              
2658             =item B<end_multipart_xhtml>
2659              
2660             Returns the XHTML required to end a multipart form.
2661              
2662             =item B<field NAME [, VALUE]>
2663              
2664             Get or set the field specified by NAME. If only a NAME argument is passed, then the field stored under the name NAME is returned. If no field exists under that name exists, then undef is returned.
2665              
2666             If both NAME and VALUE arguments are passed, then the VALUE must be a L<Rose::HTML::Form::Field> or a reference to a hash whose contents are as described in the documentation for the L<add_fields|/add_fields> method.
2667              
2668             =item B<fields [FIELDS]>
2669              
2670             If FIELDS are passed, this method L<deletes all existing fields|/delete_fields> and then calls L<add_fields|/add_fields>, passing all arguments.
2671              
2672             The return value is an ordered list of this form's field objects in list context, or a reference to this list in scalar context. The order of the fields matches the order of the field names returned by the L<field_monikers|/field_monikers> method.
2673              
2674             =item B<fields_depth_first>
2675              
2676             Returns a list (in list context) or reference to an array (in scalar context) of this form's field objects ordered according to a depth-first traversal of all L<sub-forms|/"NESTED FORMS">. Fields within a given form are ordered by L<rank|Rose::HTML::Form::Field/rank>, and all fields at a given level precede any sub-forms nested under that level.
2677              
2678             =item B<field_monikers>
2679              
2680             Returns an ordered list of field monikers in list context, or a reference to this list in scalar context. A "moniker" is a fully qualified name, including any sub-form or sub-field prefixes (e.g., "pa.person.email" as seen in the L<nested forms|/"NESTED FORMS"> section above).
2681              
2682             The order is determined by the L<compare_forms|/compare_forms> and L<compare_fields|/compare_fields> methods. The L<compare_forms|/compare_forms> method is passed the parent form of each field. If it returns a true value, then that value is used to sort the two fields being compared. If it returns false, then the L<compare_fields|/compare_fields> method is called with the two field objects as arguments and its return value is used to determine the order. See the documentation for the L<compare_forms|/compare_forms> and L<compare_fields|/compare_fields> methods for more information.
2683              
2684             =item B<field_names>
2685              
2686             This method simply calls L<field_monikers|/field_monikers>.
2687              
2688             =item B<field_rank_counter [INT]>
2689              
2690             Get or set the value of the counter used to set the L<rank|Rose::HTML::Form::Field/rank> of fields as they're L<added|/add_fields> to the form. The counter starts at 1 by default.
2691              
2692             =item B<field_type_class TYPE [, CLASS]>
2693              
2694             Given the field type string TYPE, return the name of the L<Rose::HTML::Object>-derived class mapped to that name. If a CLASS is passed, the field type TYPE is mapped to CLASS.
2695              
2696             This method is an alias for the L<object_type_class|Rose::HTML::Object/object_type_class> method inherited from L<Rose::HTML::Object>. It is an L<inherited hash|Rose::Class::MakeMethods::Generic/inherited_hash> representing the union of the hashes of all superclasses, minus any keys that are explicitly L<deleted|/delete_field_type_class> in the current class.
2697              
2698             =item B<field_type_classes [MAP]>
2699              
2700             Get or set the hash that maps object type strings to the names of the L<Rose::HTML::Object>-derived classes. This map
2701              
2702             If passed MAP (a list of type/class pairs or a reference to a hash of the same) then MAP replaces the current field type mapping. Returns a list of type/class pairs (in list context) or a reference to a hash of type/class mappings (in scalar context).
2703              
2704             This method is an alias for the L<object_type_classes|Rose::HTML::Object/object_type_classes> method inherited from L<Rose::HTML::Object>. It is an L<inherited hash|Rose::Class::MakeMethods::Generic/inherited_hash> representing the union of the hashes of all superclasses, minus any keys that are explicitly L<deleted|/delete_field_type_class> in the current class.
2705              
2706             The default mapping of type names to classes is shown in the L<Rose::HTML::Object|Rose::HTML::Object/object_type_classes> documentation.
2707              
2708             =item B<field_value NAME [, VALUE]>
2709              
2710             If passed NAME and VALUE arguments, then the L<input_value|Rose::HTML::Form::Field/input_value> of the field named NAME is set to VALUE. If passed only a NAME, then the L<internal_value|Rose::HTML::Form::Field/internal_value> of the field named NAME is returned. In other words, this:
2711              
2712             $form->field_value(zip_code => '11787');
2713              
2714             is equivalent to this:
2715              
2716             $form->field('zip_code')->input_value('11787');
2717              
2718             and this:
2719              
2720             $val = $form->field_value('zip_code');
2721              
2722             is equivalent to this:
2723              
2724             $val = $form->field('zip_code')->internal_value;
2725              
2726             If no field named NAME exists, a fatal error will occur.
2727              
2728             =item B<form NAME [, OBJECT]>
2729              
2730             Get or set the sub-form named NAME. If just NAME is passed, the specified sub-form object is returned. If no such sub-form exists, undef is returnend.
2731              
2732             If both NAME and OBJECT are passed, a new sub-form is added under NAME.
2733              
2734             NAME is a fully-qualified sub-form name. Components of the hierarchy are separated by dots ("."). OBJECT must be an object that inherits from L<Rose::HTML::Form>.
2735              
2736             =item B<forms [FORMS]>
2737              
2738             If FORMS are passed, this method L<deletes all existing forms|/delete_forms> and then calls L<add_forms|/add_forms>, passing all arguments.
2739              
2740             The return value is an ordered list of this form's sub-form objects (if any) in list context, or a reference to this list in scalar context. The order of the forms matches the order of the form names returned by the L<form_names|/form_names> method.
2741              
2742             See the L<nested forms|/"NESTED FORMS"> section to learn more about nested forms.
2743              
2744             =item B<form_name [NAME]>
2745              
2746             Get or set the name of this form. This name may or may not have any connection with the value of the "name" HTML attribute on the E<lt>formE<gt> tag. See the documentation for the L<name|/name> method for details.
2747              
2748             =item B<form_names>
2749              
2750             Returns an ordered list of form names in list context, or a reference to this list in scalar context. The order is determined by the L<compare_forms|/compare_forms> method. Note that this only lists the forms that are direct children of the current form. Forms that are nested more than one level deep are not listed.
2751              
2752             =item B<form_rank_counter [INT]>
2753              
2754             This method is deprecated and will be removed in a future release.
2755              
2756             =item B<hidden_fields>
2757              
2758             Returns one or more L<Rose::HTML::Form::Field::Hidden> objects that represent the hidden fields needed to encode all of the field values in this form.
2759              
2760             If L<coalesce_hidden_fields()|/coalesce_hidden_fields> is true, then each compound field is encoded as a single hidden field. Otherwise, each subfield of a compound field will be have its own hidden field.
2761              
2762             =item B<html_hidden_fields>
2763              
2764             Returns the HTML serialization of the fields returned by L<hidden_fields()|/hidden_fields>, joined by newlines.
2765              
2766             =item B<init_fields [PARAMS]>
2767              
2768             Initialize the fields based on L<params()|/params>. In general, this works as you'd expect, but the details are a bit complicated.
2769              
2770             The intention of L<init_fields()|/init_fields> is to set field values based solely and entirely on L<params()|/params>. That means that default values for fields should not be considered unless they are explicitly part of L<params()|/params>.
2771              
2772             In general, default values for fields exist for the purpose of displaying the HTML form with certain items pre-selected or filled in. In a typical usage scenario, those default values will end up in the web browser form submission and, eventually, as as an explicit part of part L<params()|/params>, so they are not really ignored.
2773              
2774             But to preserve the intended functionality of L<init_fields()|/init_fields>, the first thing this method does is L<clear()|/clear> the form. (This is the default. See the C<no_clear> parameter below.)
2775              
2776             If a parameter name exactly matches a field's name (note: the field's L<name|Rose::HTML::Form::Field/name>, which is not necessarily the the same as the name that the field is stored under in the form), then the (list context) value of that parameter is passed as the L<input_value()|Rose::HTML::Form::Field/input_value> for that field.
2777              
2778             If a field "isa" L<Rose::HTML::Form::Field::Compound>, and if no parameter exactly matches the L<name|Rose::HTML::Form::Field/name> of the compound field, then each subfield may be initialized by a parameter name that matches the subfield's L<name|Rose::HTML::Form::Field/name>.
2779              
2780             If a field is an "on/off" type of field (e.g., a radio button or checkbox), then the field is turned "on" only if the value of the parameter that matches the field's L<name|Rose::HTML::Form::Field/name> exactly matches (string comparison) the "value" HTML attribute of the field. If not, and if L<params_exist()|/params_exist>, then the field is set to "off". Otherwise, the field is not modified at all.
2781              
2782             PARAMS are name/value pairs. Valid parameters are:
2783              
2784             =over 4
2785              
2786             =item B<no_clear BOOL>
2787              
2788             If true, the form is not L<clear()ed|/clear> before it is initialized.
2789              
2790             =item B<recursive BOOL>
2791              
2792             If true, this method is called recursively on any L<nested sub-forms|/"NESTED FORMS">. If false, the fields in all nested sub-forms are still initialized as expected, but this is done by iterating over the "flattened" L<fields|/fields> list rather than through recursion.
2793              
2794             If this parameter is not passed, its value defaults to the value of the L<recursive_init_fields|/recursive_init_fields> object attribute.
2795              
2796             =back
2797              
2798             Examples:
2799              
2800             package RegistrationForm;
2801             ...
2802             sub build_form
2803             {
2804             my($self) = shift;
2805              
2806             $self->add_fields
2807             (
2808             name => { type => 'text', size => 25 },
2809              
2810             gender =>
2811             {
2812             type => 'radio group',
2813             choices => { 'm' => 'Male', 'f' => 'Female' },
2814             default => 'm'
2815             },
2816              
2817             hobbies =>
2818             {
2819             type => 'checkbox group',
2820             name => 'hobbies',
2821             choices => [ 'Chess', 'Checkers', 'Knitting' ],
2822             default => 'Chess'
2823             },
2824              
2825             bday = => { type => 'date split mdy' }
2826             );
2827             }
2828              
2829             ...
2830              
2831             $form = RegistrationForm->new();
2832              
2833             $form->params(name => 'John',
2834             gender => 'm',
2835             hobbies => undef,
2836             bday => '1/24/1984');
2837              
2838             # John, Male, no hobbies, 1/24/1984
2839             $form->init_fields;
2840              
2841             $form->reset;
2842             $form->params(name => 'John',
2843             bday => '1/24/1984');
2844              
2845             # No name, Male, Chess, 1/24/1984
2846             $form->init_fields(no_clear => 1);
2847              
2848             $form->reset;
2849             # Set using subfield names for "bday" compound field
2850             $form->params('name' => 'John',
2851             'bday.month' => 1,
2852             'bday.day' => 24,
2853             'bday.year' => 1984);
2854              
2855             # John, Male, no hobbies, 1/24/1984
2856             $form->init_fields();
2857              
2858             $form->reset;
2859             $form->params('bday' => '1/24/1984',
2860             'bday.month' => 12,
2861             'bday.day' => 25,
2862             'bday.year' => 1975);
2863              
2864             # No name, no gender, no hobbies, but 1/24/1984 because
2865             # the "bday" param trumps any and all subfield params.
2866             $form->init_fields();
2867              
2868             $form->reset;
2869              
2870             # Explicitly set hobbies field to Knitting...
2871             $form->field('hobbies')->input_value('Knitting');
2872              
2873             # ...but then provide a hobbies param with no value
2874             $form->params('hobbies' => undef);
2875              
2876             # Fields are not cleared, but the existence of the hobbies
2877             # param with an empty value causes the hobbies list to be
2878             # empty, instead of the default Chess. Thus:
2879             #
2880             # No name, Male, no hobbies, no birthday
2881             $form->init_fields(no_clear => 1);
2882              
2883             =item B<init_fields_with_cgi CGI [, ARGS]>
2884              
2885             This method is a shortcut for initializing the form's L<params|/params> with a CGI object and then calling L<init_fields|/init_fields>. The CGI argument is passed to the L<params_from_cgi|/params_from_cgi> method and ARGS are passed to the L<init_fields|/init_fields> method.
2886              
2887             For example, this:
2888              
2889             $form->init_fields_with_cgi($cgi, no_clear => 1);
2890              
2891             Is equivalent to this:
2892              
2893             $form->params_from_cgi($cgi);
2894             $form->init_fields(no_clear => 1);
2895              
2896             See the documentation for the L<params_from_cgi|/params_from_cgi> and L<init_fields|/init_fields> methods for more information.
2897              
2898             =item B<init_fields_with_apache APR [, ARGS]>
2899              
2900             This method is a shortcut for initializing the form's L<params|/params> with an apache request object and then calling L<init_fields|/init_fields>. The APR argument is passed to the L<params_from_apache|/params_from_apache> method and ARGS are passed to the L<init_fields|/init_fields> method.
2901              
2902             For example, this:
2903              
2904             $form->init_fields_with_apache($r, no_clear => 1);
2905              
2906             Is equivalent to this:
2907              
2908             $form->params_from_apache($r);
2909             $form->init_fields(no_clear => 1);
2910              
2911             See the documentation for the L<params_from_apache|/params_from_apache> and L<init_fields|/init_fields> methods for more information.
2912              
2913             =item B<init_with_object OBJECT>
2914              
2915             Initialize the form based on OBJECT. First, the form is L<clear()|/clear>ed. Next, for each field L<name()|Rose::HTML::Form::Field/name>, if the object has a method with the same name, then the return value of that method (called in scalar context) is passed as the L<input_value()|Rose::HTML::Form::Field/input_value> for the form field of the same name.
2916              
2917             The actual code for the L<init_with_object()|/init_with_object> method may be more clear than the description above. Essentially, it does this:
2918              
2919             sub init_with_object
2920             {
2921             my($self, $object) = @_;
2922              
2923             $self->clear();
2924              
2925             foreach my $field ($self->fields)
2926             {
2927             my $name = $field->local_name;
2928              
2929             if($object->can($name))
2930             {
2931             $field->input_value(scalar $object->$name());
2932             }
2933             }
2934             }
2935              
2936             Use this method as a "helper" when writing your own methods such as C<init_with_person()>, as described in the example in the L<overview|/OVERVIEW>. L<init_with_object()|/init_with_object> should be called in the code for subclasses of L<Rose::HTML::Form>, but never by an end-user of such classes.
2937              
2938             The convention for naming such methods is "init_with_foo", where "foo" is a (lowercase, underscore-separated, please) description of the object (or objects) used to initialize the form. You are free to accept and handle any kind or number of arguments in your "init_with_foo()"-style methods (all which you'll carefully document, of course).
2939              
2940             The field names may not match up exactly with the object method names. In such cases, you can use L<init_with_object()|/init_with_object> to handle all the fields that do match up with method names, and then handle the others manually. Example:
2941              
2942             sub init_with_person
2943             {
2944             my($self, $person) = @_;
2945              
2946             # Handle field names that match method names
2947             $self->init_with_object($person);
2948              
2949             # Manually set the non-matching or other fields
2950             $self->field('phone2')->input_value($person->alt_phone);
2951             $self->field('is_new')->input_value(1);
2952             ...
2953             }
2954              
2955             =item B<is_empty>
2956              
2957             Returns true if each L<field|/fields> and L<nested form|/forms> in this form L<is_empty()|/is_empty>, false otherwise.
2958              
2959             =item B<is_repeatable>
2960              
2961             Returns true if this form is a L<repeatable form|Rose::HTML::Form::Repeatable>, false otherwise.
2962              
2963             =item B<local_field NAME [, VALUE]>
2964              
2965             Get or set a field that is an immediate child of the current form. That is, it does not belong to a L<nested form|/"NESTED FORMS">. If the field specified by NAME does not meet these criteria, then undef is returned. In all other respects, this method behaves like the L<field|/field> method.
2966              
2967             Note that NAME should be the name as seen from the perspective of the form object upon which this method is called. So a nested form can always address its local fields using their "short" (unqualified) names even if the form is actually nested within another form.
2968              
2969             =item B<local_fields>
2970              
2971             Returns a list of fields that are immediate children of the current form (i.e., fields that do not belong to a L<nested form|/"NESTED FORMS">).
2972              
2973             =item B<local_form NAME [, OBJECT]>
2974              
2975             Get or set a form that is an immediate child of the current form. That is, it does not belong to a L<nested form|/"NESTED FORMS">. If the form specified by NAME does not meet these criteria, then undef is returned. In all other respects, this method behaves like the L<form|/form> method.
2976              
2977             Note that NAME should be the name as seen from the perspective of the form object upon which this method is called. So a nested form can always address its local sub-forms using their "short" (unqualified) names even if the parent form itself is actually nested within another form.
2978              
2979             =item B<name [NAME]>
2980              
2981             If passed a NAME argument, then the "name" HTML attribute is set to NAME.
2982              
2983             If called without any arguments, and if the "name" HTML attribute is empty, then the "name" HTML attribute is set to the L<form_name|/form_name>.
2984              
2985             Returns the value of the "name" HTML attribute.
2986              
2987             =item B<object_from_form OBJECT | CLASS | PARAMS>
2988              
2989             Returns an object built based on the contents of the form.
2990              
2991             For each field L<name()|Rose::HTML::Form::Field/name>, if the object has a method with the same name, then the L<internal_value()|Rose::HTML::Form::Field/internal_value> of the field is passed to the object method of that name. The actual code is almost as simple as this:
2992              
2993             foreach my $field ($self->fields)
2994             {
2995             my $name = $field->local_name;
2996              
2997             if($object->can($name))
2998             {
2999             $object->$name($field->internal_value);
3000             }
3001             }
3002              
3003             The only wrinkle is the case where a sub-form and a parent form have fields with the same L<local_name|Rose::HTML::Form::Field/local_name>. In that case, the field "closer" to the "root" form (in terms of the parent/child relationship tree) takes precedence. For example, consider the following fields:
3004              
3005             name
3006             vendor.name
3007             vendor.country.name
3008              
3009             The L<local_name|Rose::HTML::Form::Field/local_name> for all of these fields is C<name>, but L<object_from_form|/object_from_form> will pass the value of the C<name> field to the C<name()> method of the object. See the L<nested forms|/"NESTED FORMS"> section of the documentation for more information on nested forms.
3010              
3011             In order to return an object based on a form, L<object_from_form|/object_from_form> needs an object. If passed an OBJECT argument, then that's the object that's used. If passed a CLASS name, then a new object is constructed by calling L<new()|/new> on that class. OBJECT or CLASS may alternately be passed as a name/value pair in PARAMS.
3012              
3013             Use this method as a "helper" when writing your own methods such as C<person_from_form()>, as described in the example in the L<overview|/OVERVIEW>. L<object_from_form()|/object_from_form> should be called in the code for subclasses of L<Rose::HTML::Form>, but never by an end-user of such classes.
3014              
3015             The convention for naming such methods is "foo_from_form", where "foo" is a (lowercase, underscore-separated, please) description of the object constructed based on the values in the form's fields.
3016              
3017             The field names may not match up exactly with the object method names. In such cases, you can use L<object_from_form()|/object_from_form> to handle all the fields that do match up with method names, and then handle the others manually. Example:
3018              
3019             sub person_from_form
3020             {
3021             my($self) = shift;
3022              
3023             my $person = $self->object_from_form(class => 'Person');
3024              
3025             $person->alt_phone($self->field('phone2')->internal_value);
3026             ...
3027             return $person;
3028             }
3029              
3030             It is the caller's responsibility to ensure that the object class (C<Person> in the example above) is loaded prior to calling this method.
3031              
3032             =item B<param NAME [, VALUE]>
3033              
3034             Get or set the value of a named parameter. If just NAME is passed, then the value of the parameter of that name is returned. If VALUE is also passed, then the parameter value is set and then returned.
3035              
3036             If a parameter has multiple values, the values are returned as a reference to an array in scalar context, or as a list in list context. Multiple values are set by passing a VALUE that is a reference to an array of scalars.
3037              
3038             Failure to pass at least a NAME argument results in a fatal error.
3039              
3040             =item B<params [PARAMS]>
3041              
3042             Get or set all parameters at once.
3043              
3044             PARAMS can be a reference to a hash or a list of name/value pairs. If a parameter has multiple values, those values should be provided in the form of a reference to an array of scalar values. If the list of name/value pairs has an odd number of items, a fatal error occurs.
3045              
3046             If PARAMS is a reference to a hash, then it is accepted as-is. That is, no copying of values is done; the actual hash references is stored. If PARAMS is a list of name/value pairs, then a deep copy is made during assignment.
3047              
3048             Regardless of the arguments, this method returns the complete set of parameters in the form of a hash (in list context) or a reference to a hash (in scalar context).
3049              
3050             In scalar context, the hash reference returned is a reference to the actual hash used to store parameter names and values in the object. It should be treated as read-only.
3051              
3052             The hash returned in list context is a deep copy of the actual hash used to store parameter names and values in the object. It may be treated as read/write.
3053              
3054             =item B<params_exist>
3055              
3056             Returns true if any parameters exist, false otherwise.
3057              
3058             =item B<param_exists NAME>
3059              
3060             Returns true if a parameter named NAME exists, false otherwise.
3061              
3062             =item B<param_exists_for_field [ NAME | FIELD ]>
3063              
3064             Returns true if a L<param|/param> exists that addresses the field named NAME or the L<Rose::HTML::Form::Field>-derived object FIELD, false otherwise.
3065              
3066             This method is useful for determining if any query parameters exist that address a compound field. For example, a compound field named C<a.b.c.d> could be addressed by any one of the following query parameters: C<a>, C<a.b>, C<a.b.c>, or C<a.b.c.d>. This method also works with fields inside L<sub-form|/"NESTED FORMS">. Examples:
3067              
3068             $form = Rose::HTML::Form->new;
3069             $form->add_field(when => { type => 'datetime split mdyhms' });
3070              
3071             $form->params({ 'when.date' => '2004-01-02' });
3072              
3073             $form->param_exists_for_field('when'); # true
3074             $form->param_exists_for_field('when.date'); # true
3075             $form->param_exists_for_field('when.date.month'); # true
3076             $form->param_exists_for_field('when.time.hour'); # false
3077              
3078             $subform = Rose::HTML::Form->new;
3079             $subform->add_field(subwhen => { type => 'datetime split mdyhms' });
3080             $form->add_form(subform => $subform);
3081              
3082             $form->params({ 'subform.subwhen.date' => '2004-01-02' });
3083              
3084             $form->param_exists_for_field('subform.subwhen'); # true
3085             $form->param_exists_for_field('subform.subwhen.date'); # true
3086             $form->param_exists_for_field('subform.subwhen.date.month'); # true
3087             $form->param_exists_for_field('subform.subwhen.time.hour'); # false
3088              
3089             $form->param_exists_for_field('when'); # false
3090             $form->param_exists_for_field('when.date'); # false
3091             $form->param_exists_for_field('when.date.month'); # false
3092             $form->param_exists_for_field('when.time.hour'); # false
3093              
3094             =item B<params_from_apache APR>
3095              
3096             Set L<params|/params> by extracting parameter names and values from an apache request object. Calling this method entirely replaces the previous L<params|/params>.
3097              
3098             If running under L<mod_perl> 1.x, the APR argument may be:
3099              
3100             =over 4
3101              
3102             =item * An L<Apache> object. In this case, the L<Apache::Request> module must also be installed.
3103              
3104             =item * An L<Apache::Request> object.
3105              
3106             =back
3107              
3108             If running under L<mod_perl> 2.x, the APR may be:
3109              
3110             =over 4
3111              
3112             =item * An L<Apache2::RequestRec> object. In this case, the L<Apache2::Request> module must also be installed.
3113              
3114             =item * An L<Apache2::Request> object.
3115              
3116             =back
3117              
3118             In all cases, APR may be an object that has a C<param()> method that behaves in the following way:
3119              
3120             =over 4
3121              
3122             =item * When called in list context with no arguments, it returns a list of parameter names.
3123              
3124             =item * When called in list context with a single parameter name argument, it returns a list of values for that parameter.
3125              
3126             =back
3127              
3128             =item B<params_from_cgi CGI>
3129              
3130             Set L<params|/params> by extracting parameter names and values from a L<CGI> object. Calling this method entirely replaces the previous L<params|/params>. The CGI argument must be either a L<CGI> object or must have a C<param()> method that behaves in the following way:
3131              
3132             =over 4
3133              
3134             =item * When called in list context with no arguments, it returns a list of parameter names.
3135              
3136             =item * When called in list context with a single parameter name argument, it returns a list of values for that parameter.
3137              
3138             =back
3139              
3140             =item B<param_value_exists NAME, VALUE>
3141              
3142             Determines if a parameter of a particular name exists and has a particular value. This method returns true if the parameter named NAME exists and also has a value that is equal to (string comparison) VALUE. Otherwise, it returns false.
3143              
3144             A fatal error occurs unless both NAME and VALUE arguments are passed.
3145              
3146             =item B<parent_form [FORM]>
3147              
3148             Get or set the parent form, if any. The reference to the parent form is "weakened" using L<Scalar::Util::weaken()|Scalar::Util/weaken> in order to avoid memory leaks caused by circular references.
3149              
3150             =item B<prepare [PARAMS]>
3151              
3152             Prepare the form by calling the L<prepare|Rose::HTML::Form::Field/prepare> method on each L<field|/fields>, passing all arguments. This same method is also called for each L<sub-form|/forms>, passing all arguments plus the C<form_only> parameter with a true value.
3153              
3154             PARAMS are name/value pairs. Valid parameters are:
3155              
3156             =over 4
3157              
3158             =item B<form_only BOOL>
3159              
3160             If true, the L<prepare|Rose::HTML::Form::Field/prepare> method is not called for each L<field|/fields>.
3161              
3162             =back
3163              
3164             =item B<query_string>
3165              
3166             Returns a URI-escaped (but I<not> HTML-escaped) query string that corresponds to the current state of the form. If L<coalesce_query_string_params()|/coalesce_query_string_params> is true (which is the default), then compound fields are represented by a single query parameter. Otherwise, the subfields of each compound field appear as separate query parameters.
3167              
3168             =item B<rank [INT]>
3169              
3170             Get or set the form's rank. This value can be used for any purpose that suits you, but by default it's used by the L<compare_forms|/compare_forms> method to sort sub-forms.
3171              
3172             =item B<recursive_init_fields [BOOL]>
3173              
3174             Get or set a boolean value indicating the default value of the <recursive> parameter to the L<init_fields|/init_fields> method. This attribute, in turn, defaults to the value returned by the L<default_recursive_init_fields|/default_recursive_init_fields> class method.
3175              
3176             =item B<repeatable_form NAME [, OBJECT]>
3177              
3178             Get or set the repeatable sub-form named NAME. If just NAME is passed, the specified repeatable sub-form object is returned. If no such repeatable sub-form exists, undef is returnend.
3179              
3180             If both NAME and OBJECT are passed, a new repeatable sub-form is added under NAME.
3181              
3182             NAME is a fully-qualified sub-form name. Components of the hierarchy are separated by dots ("."). OBJECT must be an object that inherits from L<Rose::HTML::Form::Repeatable>.
3183              
3184             =item B<repeatable_forms [FORMS]>
3185              
3186             If FORMS are passed, this method L<deletes all existing repeatable forms|/delete_repeatable_forms> and then calls L<add_repeatable_forms|/add_repeatable_forms>, passing all arguments.
3187              
3188             The return value is an ordered list of this form's repeatable sub-form objects (if any) in list context, or a reference to this list in scalar context. The order of the forms matches the order of the form names returned by the L<form_names|/form_names> method.
3189              
3190             See the L<nested forms|/"NESTED FORMS"> section to learn more about nested forms, and the L<Rose::HTML::Form::Repeatable> documentation to learn more about repeatable forms.
3191              
3192             =item B<reset>
3193              
3194             Call L<reset()|Rose::HTML::Form::Field/reset> on each field object and set L<error()|Rose::HTML::Object/error> to undef.
3195              
3196             =item B<reset_fields>
3197              
3198             Call L<reset()|/reset> on each field object.
3199              
3200             =item B<self_uri>
3201              
3202             Returns a L<Rose::URI> object corresponding to the current state of the form. If L<uri_base()|/uri_base> is set, then it is included in front of what would otherwise be the start of the URI (i.e., the value of the form's "action" HTML attribute).
3203              
3204             =item B<start_html>
3205              
3206             Returns the HTML that will begin the form tag.
3207              
3208             =item B<start_xhtml>
3209              
3210             Returns the XHTML that will begin the form tag.
3211              
3212             =item B<start_multipart_html>
3213              
3214             Sets the "enctype" HTML attribute to "multipart/form-data", then returns the HTML that will begin the form tag.
3215              
3216             =item B<start_multipart_xhtml>
3217              
3218             Sets the "enctype" HTML attribute to "multipart/form-data", then returns the XHTML that will begin the form tag.
3219              
3220             =item B<trim_xy_params [BOOL]>
3221              
3222             Get or set a boolean value that determines whether or not L<params|/params> that end in ".x" or ".y" have that suffix trimmed off. This is useful for handling query parameters created by some web browsers in response to clicks on image buttons and other image-based elements. Setting this attribute will propagate the value down to all L<sub-forms|/"NESTED FORMS">.
3223              
3224             The default value is the value returned by the L<default_trim_xy_params|/default_trim_xy_params> class method.
3225              
3226             =item B<uri_base [STRING]>
3227              
3228             Get or set the URI of the form, minus the value of the "action" HTML attribute. Although the form action can be a relative URI, I suggest that it be an absolute path at the very least, leaving the L<uri_base()|/uri_base> to be the initial part of the full URI returned by L<self_uri()|/self_uri>. Example:
3229              
3230             $form->action('/foo/bar');
3231             $form->uri_base('http://www.foo.com');
3232              
3233             # http://www.foo.com/foo/bar
3234             $uri = $form->self_uri;
3235              
3236             =item B<uri_separator [CHAR]>
3237              
3238             Get or set the character used to separate parameter name/value pairs in the return value of L<query_string()|/query_string> (which is in turn used to construct the return value of L<self_uri()|/self_uri>). The default is "&".
3239              
3240             =item B<validate [PARAMS]>
3241              
3242             Validate the form by calling L<validate()|Rose::HTML::Form::Field/validate> on each field and L<validate()|/validate> on each each L<sub-form|/"NESTED FORMS">. If any field or form returns false from its C<validate()> method call, then this method returns false. Otherwise, it returns true.
3243              
3244             If this method is about to return false and the L<error|Rose::HTML::Object/error> attribute of this form is not set, then it is set to a generic error message.
3245              
3246             PARAMS are name/value pairs. Valid parameters are:
3247              
3248             =over 4
3249              
3250             =item C<cascade BOOL>
3251              
3252             If true, then the L<validate()|/validate> method of each sub-form is called, passing PARAMS, with a C<form_only> parameter set to true. The default value of the C<cascade> parameter is true. Note that all fields in all nested forms are validated regardless of the value of this parameter.
3253              
3254             =item C<form_only BOOL>
3255              
3256             If true, then the L<validate|Rose::HTML::Form::Field/validate> method is not called on the fields of this form and its sub-forms. Defaults to false, but is set to true when calling L<validate()|/validate> on sub-forms in response to the C<cascade> parameter.
3257              
3258             =back
3259              
3260             Examples:
3261              
3262             $form = Rose::HTML::Form->new;
3263             $form->add_field(foo => { type => 'text' });
3264              
3265             $subform = Rose::HTML::Form->new;
3266             $subform->add_field(bar => { type => 'text' });
3267              
3268             $form->add_form(sub => $subform);
3269              
3270             # Call validate() on fields "foo" and "sub.bar" and
3271             # call validate(form_only => 1) on the sub-form "sub"
3272             $form->validate;
3273              
3274             # Same as above
3275             $form->validate(cascade => 1);
3276              
3277             # Call validate() on fields "foo" and "sub.bar"
3278             $form->validate(cascade => 0);
3279              
3280             # Call validate(form_only => 1) on the sub-form "sub"
3281             $form->validate(form_only => 1);
3282              
3283             # Don't call validate() on any fields or sub-forms
3284             $form->validate(form_only => 1, cascade => 0);
3285              
3286             =item B<validate_field_html_attrs [BOOL]>
3287              
3288             Get or set a boolean flag that indicates whether or not the fields of this form will validate their HTML attributes. If a BOOL argument is passed, then it is passed as the argument to a call to L<validate_html_attrs()|Rose::HTML::Object/validate_html_attrs> on each field. In either case, the current value of this flag is returned.
3289              
3290             =item B<was_submitted>
3291              
3292             Returns true id L<params exist|/param_exists_for_field> for any L<field|/fields>, false otherwise.
3293              
3294             =item B<xhtml_hidden_fields>
3295              
3296             Returns the XHTML serialization of the fields returned by L<hidden_fields()|/hidden_fields>, joined by newlines.
3297              
3298             =back
3299              
3300             =head1 SUPPORT
3301              
3302             Any L<Rose::HTML::Objects> questions or problems can be posted to the L<Rose::HTML::Objects> mailing list. To subscribe to the list or search the archives, go here:
3303              
3304             L<http://groups.google.com/group/rose-html-objects>
3305              
3306             Although the mailing list is the preferred support mechanism, you can also email the author (see below) or file bugs using the CPAN bug tracking system:
3307              
3308             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Rose-HTML-Objects>
3309              
3310             There's also a wiki and other resources linked from the Rose project home page:
3311              
3312             L<http://rosecode.org>
3313              
3314             =head1 AUTHOR
3315              
3316             John C. Siracusa (siracusa@gmail.com)
3317              
3318             =head1 LICENSE
3319              
3320             Copyright (c) 2010 by John C. Siracusa. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.