| Rose-HTML-Objects documentation | Contained in the Rose-HTML-Objects distribution. |
Rose::HTML::Form::Field::DateTime::Split::MonthDayYear - Compound field for dates with separate text fields for month, day, and year.
$field =
Rose::HTML::Form::Field::DateTime::Split::MonthDayYear->new(
label => 'Date',
name => 'date',
default => '12/31/2002');
print $field->field('month')->internal_value; # "12"
print $field->internal_value; # "2002-12-31T20:00:00"
print $field->output_value; # "2002-12-31 08:00:00 PM"
$field->input_value('blah');
# "Could not parse date: blah"
$field->validate or warn $field->error;
$field->input_value('4/30/1980');
$dt = $field->internal_value; # DateTime object
print $dt->hour; # 17
print $dt->day_name; # Wednesday
print $field->html;
...
Rose::HTML::Form::Field::DateTime::Split::MonthDayYear a compound field for dates with separate text fields for month, day, and year.
This class inherits (indirectly) from both Rose::HTML::Form::Field::DateTime and Rose::HTML::Form::Field::Compound. This doesn't quite work out as expected without a bit of tweaking. We'd like inflate_value() and validate() methods to be inherited from Rose::HTML::Form::Field::DateTime, but everything else to be inherited from Rose::HTML::Form::Field::Compound.
To solve this problem, there's an intermediate class that imports the correct set of methods. This class then inherits from the intermediate class. This works, and isolates the tricky bits to a single intermediate class, but it also demonstrates the problems that can crop up when multiple inheritance is combined with a strong aversion to code duplication.
Inheritence shenanigans aside, this class is a good example of a compound field that also provides an "inflated" internal value (a DateTime object).
It is important that this class (indirectly) inherits from Rose::HTML::Form::Field::Compound. See the Rose::HTML::Form::Field::Compound documentation for more information.
Get or set the date parser object. This object must include a parse_datetime() method that takes a single string as an argument and returns a DateTime object, or undef if parsing fails.
If the parser object has an error() method, it will be called to set the error message after a failed parsing attempt.
The parser object defaults to Rose::DateTime::Parser->new().
If the parser object has a time_zone() method, this method simply calls it, passing all arguments. Otherwise, undef is returned.
Other examples of custom fields:
A text field that only accepts valid email addresses.
Uses inflate/deflate to coerce input into a fixed format.
Uses inflate/deflate to convert input to a DateTime object.
A compound field whose internal value consists of more than one object.
A simple compound field that coalesces multiple subfields into a single value.
A compound field that includes other compound fields and uses inflate/deflate convert input from multiple subfields into a DateTime object.
John C. Siracusa (siracusa@gmail.com)
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.
| Rose-HTML-Objects documentation | Contained in the Rose-HTML-Objects distribution. |
package Rose::HTML::Form::Field::DateTime::Split::MonthDayYear; use strict; use Rose::DateTime::Util(); use Rose::HTML::Object::Messages qw(:date); use base 'Rose::HTML::Form::Field::DateTime::Split'; our $VERSION = '0.606'; sub build_field { my($self) = shift; $self->add_fields ( month => { type => 'text', size => 2, maxlength => 2, class => 'month', label_id => FIELD_LABEL_MONTH, error_label_id => FIELD_ERROR_LABEL_MONTH, }, day => { type => 'text', size => 2, maxlength => 2, class => 'day', label_id => FIELD_LABEL_DAY, error_label_id => FIELD_ERROR_LABEL_DAY, }, year => { type => 'text', size => 4, maxlength => 4, class => 'year', label_id => FIELD_LABEL_YEAR, error_label_id => FIELD_ERROR_LABEL_YEAR, }, ); } sub decompose_value { my($self, $value) = @_; return undef unless(defined $value); my $date = $self->SUPER::inflate_value($value); unless($date) { no warnings; my($month, $day, $year) = split('/', $value); return { month => $month || '', day => $day || '', year => $year || '', } } my($month, $day, $year) = Rose::DateTime::Util::format_date($date, '%m', '%d', '%Y'); return { month => $month, day => $day, year => $year, }; } sub is_full { my($self) = shift; my $count = grep { defined && length } map { $self->field($_)->internal_value } qw(month day year); return $count == 3 ? 1 : 0; } sub coalesce_value { my($self) = shift; return join('/', map { defined($_) ? $_ : '' } map { $self->field($_)->internal_value } qw(month day year)); } sub deflate_value { my($self, $date) = @_; return $self->input_value_filtered unless($date); return Rose::DateTime::Util::format_date($date, '%m/%d/%Y'); } sub html_field { my($self) = shift; return '<span class="date">' . $self->field('month')->html_field . '/' . $self->field('day')->html_field . '/' . $self->field('year')->html_field . '</span>'; } sub xhtml_field { my($self) = shift; return '<span class="date">' . $self->field('month')->xhtml_field . '/' . $self->field('day')->xhtml_field . '/' . $self->field('year')->xhtml_field . '</span>'; } if(__PACKAGE__->localizer->auto_load_messages) { __PACKAGE__->localizer->load_all_messages; } use utf8; # The __DATA__ section contains UTF-8 text 1; __DATA__ [% LOCALE en %] FIELD_LABEL_MONTH = "Month" FIELD_LABEL_DAY = "Day" FIELD_LABEL_YEAR = "Year" FIELD_ERROR_LABEL_MONTH = "month" FIELD_ERROR_LABEL_DAY = "day" FIELD_ERROR_LABEL_YEAR = "year" [% LOCALE de %] FIELD_LABEL_MONTH = "Monat" FIELD_LABEL_DAY = "Tag" FIELD_LABEL_YEAR = "Jahr" FIELD_ERROR_LABEL_MONTH = "Monat" FIELD_ERROR_LABEL_DAY = "Tag" FIELD_ERROR_LABEL_YEAR = "Jahr" [% LOCALE fr %] FIELD_LABEL_MONTH = "Mois" FIELD_LABEL_DAY = "Jour" FIELD_LABEL_YEAR = "Année" FIELD_ERROR_LABEL_MONTH = "mois" FIELD_ERROR_LABEL_DAY = "jour" FIELD_ERROR_LABEL_YEAR = "année" [% LOCALE bg %] FIELD_LABEL_MONTH = "ÐеÑеÑ" FIELD_LABEL_DAY = "Ðен" FIELD_LABEL_YEAR = "Ðодина" FIELD_ERROR_LABEL_MONTH = "меÑеÑ" FIELD_ERROR_LABEL_DAY = "ден" FIELD_ERROR_LABEL_YEAR = "година" __END__