From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

use Moose;
use HTML::FormFu::Constants qw( $EMPTY_STR $SPACE );
has split => ( is => 'rw', traits => ['Chained'] );
has join => ( is => 'rw', traits => ['Chained'] );
has field_order => ( is => 'rw', traits => ['Chained'] );
sub deflator {
my ( $self, $value ) = @_;
return if !defined $value || $value eq $EMPTY_STR;
my ( $multi, @fields ) = @{ $self->parent->get_fields };
my $split
= defined $self->split
? $self->split
: qr/$SPACE+/;
my $join
= defined $self->join
? $self->join
: $SPACE;
my @parts = CORE::split $split, $value;
if ( my $order = $self->field_order ) {
my @new_order;
FIELD:
for my $i (@$order) {
for my $field (@fields) {
if ( $field->name eq $i ) {
push @new_order, $field;
next FIELD;
}
}
}
@fields = @new_order;
}
my %value;
for my $i ( 0 .. $#fields ) {
# if there are more parts than fields, join the extra ones
# to make the final field's value
if ( $i == $#fields ) {
my $default = CORE::join $join, @parts[ $i .. $#parts ];
$fields[$i]->default($default);
$value{ $fields[$i]->name } = $default;
}
else {
$fields[$i]->default( $parts[$i] );
$value{ $fields[$i]->name } = $parts[$i];
}
}
return \%value;
}
__PACKAGE__->meta->make_immutable;
1;
__END__
=head1 NAME
HTML::FormFu::Deflator::CompoundSplit - CompoundSplit deflator
=head1 SYNOPSIS
---
element:
- type: Multi
name: address
elements:
- name: number
- name: street
deflator:
- type: CompoundSplit
# set the default
$form->get_field('address')->default( $address );
=head1 DESCRIPTION
Deflator to allow you to set several field's values at once.
For use with a L<HTML::FormFu::Element::Multi> group of fields.
A L<default|HTML::FormFu::Element::_Field/default> value passed to the
L<Multi|HTML::FormFu::Element::Multi> field will be split according to the
L</split> setting, and its resulting parts passed to its child elements.
=head1 METHODS
=head2 split
Arguments: $regex
Default Value: C<qr/ +/>
Regex used to split the default value. Defaults to a regex matching 1 or more
space characters.
=head2 join
Arguments: $string
Default Value: C<' '>
If spliting the value results in more parts than there are fields, any extra
parts are joined again to form the value for the last field. The value of
L</join> is used to join these values.
Defaults to a single space.
For example, if the Multi element contains fields C<number> and C<name>,
and is given the value C<10 Downing Street>; when split this results in 3
parts: C<10>, C<Downing> and C<Street>. In this case, the 1st part, C<10> is
assigned to the first field, and the 2nd and 3rd parts are re-joined with a
space to give the single value C<Downing Street>, which is assigned to the
2nd field.
=head2 field_order
Arguments: \@order
If the parts from the split value should be assigned to the fields in a
different order, you must provide an arrayref containing the names, in the
order they should be assigned to.
---
element:
- type: Multi
name: address
elements:
- name: street
- name: number
deflator:
- type: CompoundSplit
field_order:
- number
- street
=head1 AUTHOR
Carl Franks
=head1 LICENSE
This library is free software, you can redistribute it and/or modify it under
the same terms as Perl itself.
=cut