File Coverage

blib/lib/Rose/HTML/Form/Field/Compound.pm
Criterion Covered Total %
statement 139 147 94.5
branch 47 58 81.0
condition 16 22 72.7
subroutine 32 34 94.1
pod 20 24 83.3
total 254 285 89.1


line stmt bran cond sub pod time code
1              
2             use strict;
3 9     9   1246  
  9         19  
  9         236  
4             use Carp();
5 9     9   41  
  9         17  
  9         162  
6             use Rose::HTML::Object::Errors qw(:field);
7 9     9   396 use Rose::HTML::Object::Messages qw(:field);
  9         25  
  9         222  
8 9     9   52  
  9         19  
  9         47  
9             use base qw(Rose::HTML::Form::Field Rose::HTML::Form::Field::Collection);
10 9     9   55  
  9         24  
  9         2995  
11             use Rose::HTML::Form::Constants qw(FF_SEPARATOR);
12 9     9   57  
  9         16  
  9         9902  
13             our $VERSION = '0.611';
14              
15             # Multiple inheritence never quite works out the way I want it to...
16             Rose::HTML::Form::Field::Collection->import_methods
17             (
18             'hidden_field',
19             'hidden_fields',
20             'html_hidden_field',
21             'xhtml_hidden_field',
22             'html_hidden_fields',
23             'xhtml_hidden_fields',
24             );
25              
26             our $Debug = undef;
27              
28             {
29             my($self) = shift;
30             my(%args) = @_;
31 84     84 1 169  
32 84         233 if(exists $args{'name'})
33             {
34 84 50       207 $self->name(delete $args{'name'});
35             }
36 84         291 else
37             {
38             Carp::croak __PACKAGE__, "-derived fields require a 'name' parameter in the constructor";
39             }
40 0         0  
41             $self->{'fields'} ||= {};
42              
43 84   50     274 $self->build_field();
44              
45 84         377 local $self->{'in_init'} = 1;
46             $self->SUPER::init(@_);
47 84         378 }
48 84         311  
49              
50             {
51 0     0 0 0 Carp::croak "Cannot set children() for a pseudo-group ($_[0])" if(@_ > 1);
52             return wantarray ? () : [];
53             }
54              
55 4 50   4 1 17  
56 4 100       23  
57             {
58             my($self, %fields) = @_;
59 4     4 1 47  
60             foreach my $field_name (keys %fields)
61       1 1   {
62             my $field = $self->field($field_name) ||
63             Carp::croak "No such field: $field_name";
64              
65 1     1 0 5 if($field->isa('Rose::HTML::Form::Field::Group'))
66             {
67 1         5 $Debug && warn "$self $field_name(s) = $fields{$field_name}\n";
68             $field->_set_input_value($fields{$field_name});
69 3   33     8 }
70             else
71             {
72 3 50       19 $Debug && warn "$self $field_name = $fields{$field_name}\n";
73             $field->_set_input_value($fields{$field_name});
74 0 0       0 }
75 0         0 }
76             }
77              
78              
79 3 50       6 {
80 3         12 my($self) = shift;
81              
82             $self->SUPER::resync_name();
83             $self->resync_field_names;
84             }
85 2     2 1 8  
  6         18  
86 2     2 1 7 {
  6         17  
87             my($self) = shift;
88              
89             if(@_)
90 327     327 0 537 {
91             $self->local_name(shift);
92 327         798 $self->resync_field_names;
93 327         929 return $self->fq_name;
94             }
95              
96             return $self->fq_name;
97             }
98 1521     1521 1 2598  
99             {
100 1521 100       2623 my $self = shift;
101              
102 171         500 $self->_set_input_value(undef);
103 171         538 $self->clear_fields();
104 171         463 $self->error(undef);
105             $self->SUPER::clear();
106             }
107 1350         2626  
108             {
109             my($self) = shift;
110              
111             $self->reset_fields();
112 275     275 1 395 $self->SUPER::reset();
113             $self->is_cleared(0);
114 275         713 }
115 275         872  
116 275         1548  
117 275         606 # Evil hash grab for efficiency. May change to shift->input_value()
118             # if it becomes a problem someday...
119              
120             {
121             my($self, $value, $type) = @_;
122 12     12 1 30  
123             #$type ||= 'input_value';
124 12         69  
125 12         56 my $method = ((!$type || $type eq 'input_value')) ? '_set_input_value' : $type;
126 12         41  
127             if(my $split = $self->decompose_value($value))
128             {
129 4     4 1 12 while(my($name, $val) = each(%$split))
130             {
131             #$self->field($name)->$type($val);
132             $self->field($name)->$method($val);
133 3     3 1 7 }
134             }
135             }
136              
137 711     711 0 1231 {
138             my($self) = shift;
139              
140             if(@_)
141 711 100 66     2353 {
142             my $value = $self->SUPER::default_value(@_);
143 711 100       1739 $self->distribute_value($value, 'default_value');
144             }
145 83         415  
146             return $self->SUPER::default_value;
147             }
148 238         596  
149             *auto_invalidate_parents = \&Rose::HTML::Form::Field::auto_invalidate_parents;
150              
151             {
152             my($self) = shift;
153              
154             $self->SUPER::invalidate_value();
155 1265     1265 1 1720  
156             if($self->_is_full)
157 1265 100       2050 {
158             $self->_set_input_value($self->coalesce_value);
159 7         28 }
160 7         27 else
161             {
162             if($self->is_empty)
163 1265         2667 {
164             $self->has_partial_value(0);
165             }
166             else
167             {
168             $self->has_partial_value(1);
169             }
170 89     89 1 139  
171             $self->_set_input_value(undef);
172 89         430 }
173              
174 89 100       162 my $parent = $self->parent_field;
175              
176 19         68 if($parent)
177             {
178             $parent->invalidate_value();
179             }
180 70 100       174  
181             return;
182 18         41 }
183              
184             {
185             my($self, $name) = (shift, shift);
186 52         279 my $field = $self->field($name) or Carp::croak "No such subfield '$name'";
187             $field->_set_input_value(@_);
188             }
189 70         315  
190             {
191             my($self) = shift;
192 89         216  
193             if(@_)
194 89 100       178 {
195             my $value = $self->SUPER::input_value(@_);
196 27         63  
197             if((my $parent = $self->parent_field) && $self->auto_invalidate_parent)
198             {
199 89         193 $parent->invalidate_value;
200             }
201              
202             $self->distribute_value($value, 'input_value');
203             }
204 4     4 1 9  
205 4 50       11 my $ret = $self->SUPER::input_value;
206 4         12  
207             if(defined $ret || $self->is_empty || $self->has_partial_value)
208             {
209             return $ret;
210             }
211 1153     1153 1 2828  
212             return $self->coalesce_value;
213 1153 100       2068 }
214              
215 704         1496 {
216             my($self) = shift;
217 704 50 66     1401  
218             foreach my $field ($self->fields)
219 0         0 {
220             return 0 unless($field->is_empty);
221             }
222 704         1331  
223             return 1;
224             }
225 1153         2311  
226             {
227 1153 100 100     2984 my($self) = shift;
      100        
228              
229 1123         2725 foreach my $field ($self->fields)
230             {
231             return 0 if($field->is_empty);
232 30         221 }
233              
234             return 1;
235             }
236              
237 1397     1397 1 1982 {
238             my($self) = shift;
239 1397         2720  
240             if($self->required)
241 4165 100       18105 {
242             my @missing;
243              
244 1223         8117 foreach my $field ($self->fields)
245             {
246             no warnings 'uninitialized';
247             unless(length $field->input_value_filtered)
248             {
249 72     72 1 96 push(@missing, sub { $field->error_label || $field->local_name });
250             }
251 72         286 }
252              
253 148 100       1009 if(@missing)
254             {
255             if(@missing == $self->num_fields)
256 38         567 {
257             return $self->SUPER::validate(@_);
258             }
259              
260             $self->error_id(FIELD_REQUIRED, { missing => \@missing });
261 23     23 1 41 return 0;
262             }
263 23 100       72 }
264              
265 5         25 return $self->SUPER::validate(@_);
266             }
267 5         13  
268             {
269 9     9   68 my($self) = shift;
  9         19  
  9         1915  
270 15 100       40  
271             foreach my $field ($self->fields)
272 11 100   22   46 {
  22         55  
273             $field->disabled(@_) if($field->can('disabled'));
274             }
275             }
276 5 50       18  
277             {
278 5 100       26 my($self, %args) = @_;
279              
280 2         7 my $error_id = $args{'error_id'};
281             my $msg_class = $args{'msg_class'};
282             my $args = $args{'args'} || [];
283 3         29  
284 3         11 no warnings 'uninitialized';
285             if($error_id == FIELD_REQUIRED)
286             {
287             my $msg = $msg_class->new(args => $args);
288 18         137  
289             if(ref $args eq 'HASH' && keys %$args)
290             {
291             if($args->{'missing'})
292             {
293 0     0 1 0 if(@{$args->{'missing'}} > 1)
294             {
295 0         0 $msg->id(FIELD_REQUIRED_SUBFIELDS);
296             }
297 0 0       0 else
298             {
299             $msg->id(FIELD_REQUIRED_SUBFIELD);
300             }
301             }
302             else
303 11     11 1 118 {
304             $msg->id(FIELD_REQUIRED_LABELLED);
305 11         30 }
306 11         28 }
307 11   100     50 else
308             {
309 9     9   76 $msg->id(FIELD_REQUIRED_GENERIC);
  9         21  
  9         1585  
310 11 100       42 }
311              
312 5         21 return $msg;
313             }
314 5 100 66     45  
315             return undef;
316 4 100       11 }
317              
318 3 100       6 if(__PACKAGE__->localizer->auto_load_messages)
  3         9  
319             {
320 2         8 __PACKAGE__->localizer->load_all_messages;
321             }
322              
323             use utf8; # The __DATA__ section contains UTF-8 text
324 1         5  
325             1;
326              
327              
328             [% LOCALE en %]
329 1         4  
330             FIELD_REQUIRED_SUBFIELD = "Missing [@missing]."
331             FIELD_REQUIRED_SUBFIELDS = "Missing [@missing]."
332              
333             [% LOCALE de %]
334 1         3  
335             FIELD_REQUIRED_SUBFIELD = "[@missing] fehlt."
336             FIELD_REQUIRED_SUBFIELDS = "[@missing] fehlen."
337 5         18  
338             [% LOCALE fr %]
339              
340 6         23 FIELD_REQUIRED_SUBFIELD = "Le champ [@missing] manque."
341             FIELD_REQUIRED_SUBFIELDS = "Les champs [@missing] manquent."
342              
343             [% LOCALE bg %]
344              
345             FIELD_REQUIRED_SUBFIELD = "Непопълнени поле [@missing]."
346             FIELD_REQUIRED_SUBFIELDS = "Непопълнени полета [@missing]."
347              
348 9     9   59 __END__
  9         17  
  9         61  
349              
350             =head1 NAME
351              
352             Rose::HTML::Form::Field::Compound - Base class for field objects that contain other field objects.
353              
354             =head1 SYNOPSIS
355              
356             package MyFullNameField;
357              
358             use base qw(Rose::HTML::Form::Field::Compound
359             Rose::HTML::Form::Field::Text);
360              
361             sub build_field
362             {
363             my($self) = shift;
364              
365             $self->add_fields
366             (
367             first => { type => 'text', size => 15, maxlength => 50 },
368             middle => { type => 'text', size => 15, maxlength => 50 },
369             last => { type => 'text', size => 20, maxlength => 50 },
370             );
371             }
372              
373             sub coalesce_value
374             {
375             my($self) = shift;
376             return join(' ', map { defined($_) ? $_ : '' }
377             map { $self->field($_)->internal_value }
378             qw(first middle last));
379             }
380              
381             sub decompose_value
382             {
383             my($self, $value) = @_;
384              
385             return undef unless(defined $value);
386              
387             if($value =~ /^(\S+)\s+(\S+)\s+(\S+)$/)
388             {
389             return
390             {
391             first => $1,
392             middle => $2,
393             last => $3,
394             };
395             }
396              
397             my @parts = split(/\s+/, $value);
398              
399             if(@parts == 2)
400             {
401             return
402             {
403             first => $parts[0],
404             middle => undef,
405             last => $parts[1],
406             };
407             }
408              
409             return
410             {
411             first => $parts[0],
412             middle => $parts[1],
413             last => join(' ', @parts[2 .. $#parts]),
414             };
415             }
416              
417             # Override these methods to determine how sub-fields are arranged
418             sub html_field { ... }
419             sub xhtml_field { ... }
420             ...
421              
422              
423             use MyFullNameField;
424              
425             $field =
426             MyFullNameField->new(
427             label => 'Full Name',
428             name => 'name',
429             default => 'John Doe');
430              
431             print $field->internal_value; # "John Doe"
432              
433             $field->input_value('Steven Paul Jobs');
434              
435             print $field->field('middle')->internal_value; # "Paul"
436              
437             print $field->html;
438             ...
439              
440             =head1 DESCRIPTION
441              
442             L<Rose::HTML::Form::Field::Compound> is a base class for compound fields. A compound field is one that contains other fields. The example in the L<SYNOPSIS> is a full name field made up of three separate text fields, one each for first, middle, and last name. Compound fields can also contain other compound fields.
443              
444             Externally, a compound field must field look and behave as if it is a single, simple field. Although this can be done in many ways, it is important for all compound fields to actually inherit from L<Rose::HTML::Form::Field::Compound>. L<Rose::HTML::Form> uses this relationship in order to identify compound fields and handle them correctly. Any compound field that does not inherit from L<Rose::HTML::Form::Field::Compound> will not work correctly with L<Rose::HTML::Form>.
445              
446             This class inherits from, and follows the conventions of, L<Rose::HTML::Form::Field>. Inherited methods that are not overridden will not be documented a second time here. See the L<Rose::HTML::Form::Field> documentation for more information.
447              
448             =head1 HIERARCHY
449              
450             A L<Rose::HTML::Form::Field::Compound>-derived object behaves as if it is a single L<field|Rose::HTML::Form::Field> made up of a group of sibling elements. These siblings are available through the L<fields|/fields> method.
451              
452             See the "hierarchy" sections of the L<Rose::HTML::Form::Field/HIERARCHY> and L<Rose::HTML::Form/HIERARCHY> documentation for more information about how field objects that are really "groups of siblings" behave with respect to the the child-related methods inherited from L<Rose::HTML::Object>.
453              
454             =head1 SUBCLASSING
455              
456             Actual compound fields must override the following methods: L<build_field()|/build_field>, L<decompose_value()|/decompose_value>, and L<coalesce_value()|/coalesce_value>. The required semantics of those methods are described in the L<OBJECT METHODS> section below.
457              
458             =head1 SUBFIELD ADDRESSING
459              
460             Subfields are fields that are contained within another field. A field that has sub-fields is called a compound field. It is important to HTML form initialization that sub-fields be addressable from the top level. Since fields can be arbitrarily nested, some form of hierarchy must also exist in the field addressing scheme.
461              
462             To that end, compound fields use the "." character to partition the namespace. For example, the "month" sub-field of a compound field named "date" could be addressed from the L<form|Rose::HTML::Form> that contains the field using the name "date.month". As a consequence of this convention, I<field names may not contain periods>.
463              
464             Subfields are addressed by their "relative" names from the perspective of the caller. For example, the L<Rose::HTML::Form::Field::DateTime::Split::MDYHMS> custom field class contains a two compound fields: one for the time (split into hours, minutes, seconds, and AM/PM) and one for the date (split into month, day, and year). Here are a few ways to address the various sub-fields.
465              
466             $datetime_field =
467             Rose::HTML::Form::Field::DateTime::Split::MDYHMS->new(
468             name => 'datetime');
469              
470             ## Get the (compound) sub-field containing the month, day, and year
471             $mdy_field = $datetime_field->field('date');
472              
473              
474             ## Get the year sub-field of the month/day/year sub-field
475             ## in two different ways:
476              
477             # Fully-qualified sub-field access
478             $year_field = $datetime_field->field('date.year');
479              
480             # Relative sub-field access
481             $year_field = $datetime_field->field('date')->field('year');
482              
483             See the L<Rose::HTML::Form> documentation for more information on how forms address and initialize fields based on query parameter names.
484              
485             =head1 VALIDATION
486              
487             It is not the job of the L<coalesce_value()|/coalesce_value> or L<decompose_value()|/decompose_value> methods to validate input. That's the job of the L<validate()|Rose::HTML::Form::Field/validate> method in L<Rose::HTML::Form::Field>.
488              
489             But as you'll see when you start to write your own L<decompose_value()|/decompose_value> methods, it's often nice to know whether the input is valid before you try to decompose it into sub-field values. Valid input can usually be divided up very easily, whereas invalid input requires some hard decisions to be made. Consequently, most L<decompose_value()|/decompose_value> methods have one section for handling valid input, and another that makes a best-effort to handle invalid input.
490              
491             There are several ways to determine whether or not a value passed to L<decompose_value()|/decompose_value> is valid. You could actually call L<validate()|Rose::HTML::Form::Field/validate>, but that is technically a violation of the API since L<decompose_value()|/decompose_value> only knows that it's supposed to divvy up the value that it is passed. It is merely assuming that this value is also the current value of the field. In short, don't do that.
492              
493             The L<decompose_value()|/decompose_value> method could try to validate the input directly, of course. But that seems like a duplication of code. It might work, but it is more effort.
494              
495             The recommended solution is to rely on the fact that most overridden L<inflate_value()|Rose::HTML::Form::Field/inflate_value> methods serve as an alternate form of validation. Really, the L<decompose_value()|/decompose_value> method doesn't I<want> to "validate" in the same way that L<validate()|Rose::HTML::Form::Field/validate> does. Imagine a month/day/year compound field that only accepts dates in the 1990s. As far as L<validate()|Rose::HTML::Form::Field/validate> is concerned, 12/31/2002 is an invalid value. But as far as L<decompose_value()|/decompose_value> is concerned, it's perfectly fine and can be parsed and divided up into sub-field values easily.
496              
497             This is exactly the determination that many overridden L<inflate_value()|Rose::HTML::Form::Field/inflate_value> methods must also make. For example, that month/day/year compound field may use a L<DateTime> object as its internal value. The L<inflate_value()|Rose::HTML::Form::Field/inflate_value> method must parse a date string and produce a L<DateTime> value. The L<decompose_value()|/decompose_value> method can use that to its advantage. Example:
498              
499             sub decompose_value
500             {
501             my($self, $value) = @_;
502              
503             return undef unless(defined $value);
504              
505             # Use inflate_value() to do the dirty work of
506             # sanity checking the value for us
507             my $date = $self->SUPER::inflate_value($value);
508              
509             # Garbage input: try to do something sensible
510             unless($date)
511             {
512             my($month, $day, $year) = split('/', $value);
513              
514             return
515             {
516             month => $month || '',
517             day => $day || '',
518             year => $year || '',
519             }
520             }
521              
522             # Valid input: divide up appropriately
523             return
524             {
525             month => $date->month,
526             day => $date->day,
527             year => $date->year,
528             };
529             }
530              
531             This technique is sound because both L<decompose_value()|/decompose_value> and L<inflate_value()|Rose::HTML::Form::Field/inflate_value> work only with the input they are given, and have no reliance on the state of the field object itself (unlike L<validate()|Rose::HTML::Form::Field/validate>).
532              
533             If the L<inflate_value()|Rose::HTML::Form::Field/inflate_value> method is not being used, then L<decompose_value()|/decompose_value> must sanity check its own input. But this code is not necessarily the same as the code in L<validate()|Rose::HTML::Form::Field/validate>, so there is no real duplication.
534              
535             =head1 OBJECT METHODS
536              
537             =over 4
538              
539             =item B<add_field ARGS>
540              
541             Convenience alias for L<add_fields()|/add_fields>.
542              
543             =item B<add_fields ARGS>
544              
545             Add the fields specified by ARGS to the list of sub-fields in this compound field.
546              
547             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.
548              
549             If an argument is anything else, it is used as the field name, and the next argument is used as the field object to store under that name. If the next argument is not an object derived from L<Rose::HTML::Form::Field>, then a fatal error occurs.
550              
551             The field object's L<name()|Rose::HTML::Form::Field/name> is set to the name that it is stored under, and its L<parent_field()|Rose::HTML::Form::Field/parent_field> is set to the form object.
552              
553             Returns the full list of field objects, sorted by field name, in list context, or a reference to a list of the same in scalar context.
554              
555             Examples:
556              
557             $name_field =
558             Rose::HTML::Form::Field::Text->new(name => 'name',
559             size => 25);
560              
561             $email_field =
562             Rose::HTML::Form::Field::Text->new(name => 'email',
563             size => 50);
564              
565             # Field arguments
566             $compound_field->add_fields($name_field, $email_field);
567              
568             # Name/field pairs
569             $compound_field2->add_fields(name => $name_field,
570             email => $email_field);
571              
572             # Mixed
573             $compound_field3->add_fields($name_field,
574             email => $email_field);
575              
576             =item B<auto_invalidate_parents [BOOL]>
577              
578             Get or set a boolean value that indicates whether or not the internal value of any parent fields are automatically invalidated when the input value of this field is set. The default is true.
579              
580             =item B<build_field>
581              
582             This method must be overridden by subclasses. Its job is to build the compound field by creating and then adding the sub-fields. Example:
583              
584             sub build_field
585             {
586             my($self) = shift;
587              
588             $self->add_fields
589             (
590             first => { type => 'text', size => 15, maxlength => 50 },
591             middle => { type => 'text', size => 15, maxlength => 50 },
592             last => { type => 'text', size => 20, maxlength => 50 },
593             );
594             }
595              
596             See the documentation for L<add_fields()|/add_fields> for a full description of the arguments it accepts.
597              
598             =item B<coalesce_value>
599              
600             This method must be overridden by subclasses. It is responsible for combining the values of the sub-fields into a single value. Example:
601              
602             sub coalesce_value
603             {
604             my($self) = shift;
605             return join(' ', map { defined($_) ? $_ : '' }
606             map { $self->field($_)->internal_value }
607             qw(first middle last));
608             }
609              
610             The value returned must be suitable as an input value. See the L<Rose::HTML::Form::Field> documentation for more information on input values.
611              
612             =item B<decompose_value VALUE>
613              
614             This method must be overridden by subclasses. It is responsible for distributing the input value VALUE amongst the various sub-fields. This is harder than you might expect, given the possibility of invalid input. Nevertheless, subclasses must try to divvy up even garbage values such that they eventually produce output values that are equivalent to the original input value when fed back through the system.
615              
616             The method should return a reference to a hash of sub-field-name/value pairs.
617              
618             In the example below, the method's job is to decompose a full name into first, middle, and last names. It is not very heroic in its efforts to parse the name, but it at least tries to ensure that every significant piece of the value ends up back in one of the sub-fields.
619              
620             sub decompose_value
621             {
622             my($self, $value) = @_;
623              
624             return undef unless(defined $value);
625              
626             # First, middle, and last names all present
627             if($value =~ /^(\S+)\s+(\S+)\s+(\S+)$/)
628             {
629             return
630             {
631             first => $1,
632             middle => $2,
633             last => $3,
634             };
635             }
636              
637             my @parts = split(/\s+/, $value);
638              
639             # First and last?
640             if(@parts == 2)
641             {
642             return
643             {
644             first => $parts[0],
645             middle => undef,
646             last => $parts[1],
647             };
648             }
649              
650             # Oh well, at least try to make sure all the non-whitespace
651             # characters get fed back into the field
652             return
653             {
654             first => $parts[0],
655             middle => $parts[1],
656             last => join(' ', @parts[2 .. $#parts]),
657             };
658             }
659              
660             =item B<disabled [BOOL]>
661              
662             This method calls the C<disabled()> method on all L<fields|/fields> that possess such a method, passing all arguments. Set to true to disable all eligible sub-fields, false to enable them.
663              
664             =item B<field NAME [, VALUE]>
665              
666             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.
667              
668             If both NAME and VALUE arguments are passed, then the field VALUE is stored under the name NAME. If VALUE is not an object derived from L<Rose::HTML::Form::Field>, a fatal error occurs.
669              
670             =item B<fields>
671              
672             Returns the full list of field objects, sorted by field name, in list context, or a reference to a list of the same in scalar context.
673              
674             =item B<field_value NAME>
675              
676             Returns the L<internal_value|Rose::HTML::Form::Field/internal_value> of the sub-field named NAME. In other words, this:
677              
678             $val = $field->field_value('zip_code');
679              
680             is just a shorter way to write this:
681              
682             $val = $field->field('zip_code')->internal_value;
683              
684             =item B<html_field>
685              
686             Returns the HTML serialization of the field. The default implementation calls L<html_field|Rose::HTML::Form::Field/html_field> on each of the L<fields|/fields> and then concatenates and the results. Override this method in your compound field subclass to lay out your sub-fields as desired.
687              
688             =item B<invalidate_value>
689              
690             Invalidates the field's value, and the value of all of its parent fields, and so on. This will cause the field's values to be recreated the next time they are retrieved.
691              
692             =item B<is_empty>
693              
694             Returns true if all of the sub-fields are empty, false otherwise.
695              
696             =item B<is_full>
697              
698             Returns false if any of the sub-fields are empty, true otherwise. Subclasses can override this method to indicate that a valid value does not require all sub-fields to be non-empty.
699              
700             For example, consider a compound time field with sub-fields for hours, minutes, seconds, and AM/PM. It may only require the hour and AM/PM sub-fields to be filled in. It could then assume values of zero for all of the empty sub-fields.
701              
702             Note that this behavior is different than making "00" the default values of the minutes and seconds sub-fields. Default values are shown in the HTML serializations of fields, so the minutes and seconds fields would be pre-filled with "00" (unless the field is cleared--see L<Rose::HTML::Form::Field>'s L<reset|Rose::HTML::Form::Field/reset> and L<clear|Rose::HTML::Form::Field/clear> methods for more information).
703              
704             If a subclass does override the C<is_full> method in order to allow one or more empty sub-fields while still considering the field "full," the subclass must also be sure that its L<coalesce_value|/coalesce_value> method accounts for and handles the possibility of empty fields.
705              
706             See the L<Rose::HTML::Form::Field::Time::Split::HourMinuteSecond> source code for an actual implementation of the behavior described above. In particular, look at the implementation of the C<is_full> and C<coalesce_value> methods.
707              
708             =item B<subfield_input_value NAME [, VALUE]>
709              
710             Get or set the input value of the sub-field named NAME. If there is no sub-field by that name, a fatal error will occur.
711              
712             This method has the same effect as fetching the sub-field using the L<field|/field> method and then calling L<input_value|Rose::HTML::Form::Field/input_value> directly on it, but with one important exception. Setting a sub-field input value using the L<subfield_input_value|/subfield_input_value> method will B<not> invalidate the value of the parent field.
713              
714             This method is therefore essential for implementing compound fields that need to set their sub-field values directly. Without it, any attempt to do so would cause the compound field to invalidate itself.
715              
716             See the source code for L<Rose::HTML::Form::Field::DateTime::Range>'s L<inflate_value|Rose::HTML::Form::Field::DateTime::Range/inflate_value> method for a real-world usage example of the L<subfield_input_value|/subfield_input_value> method.
717              
718             =item B<xhtml_field>
719              
720             Returns the XHTML serialization of the field. The default implementation calls L<xhtml_field|Rose::HTML::Form::Field/xhtml_field> on each of the L<fields|/fields> and then concatenates and the results. Override this method in your compound field subclass to lay out your sub-fields as desired.
721              
722             =back
723              
724             =head1 SUPPORT
725              
726             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:
727              
728             L<http://groups.google.com/group/rose-html-objects>
729              
730             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:
731              
732             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Rose-HTML-Objects>
733              
734             There's also a wiki and other resources linked from the Rose project home page:
735              
736             L<http://rosecode.org>
737              
738             =head1 AUTHOR
739              
740             John C. Siracusa (siracusa@gmail.com)
741              
742             =head1 LICENSE
743              
744             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.