NAME
Data::MuForm::Manual::Cookbook - Cookbook recipes for using MuForm
VERSION
version 0.04
NAME
Data::MuForm::Manual::Cookbook
RECIPES
Update all fields
In FormHandler you can do something like:
sub build_update_subfields {{
by_flag => { contains => { wrapper_class => ['rep_elem'] } },
by_type => { 'Select' => { wrapper_class => ['sel_wrapper'] },
'Boolean' => { element_class => ['sel_elem'] },
},
}}
You can achieve the equivalent in MuForm with:
sub after_build_fields {
my $self = shift;
foreach my $field ( $self->all_repeatable_fields ) {
$field->init_instance({ 'ra.wa.class' => ['rep_elem'] });
}
# the 'index' contains all fields, not just top level fields
foreach my $field ( values %{$self->index} ) {
if ( $field->type eq 'Select' ) {
$field->render_args->{wrapper_attr}{class} = ['sel_wrapper'];
}
elsif ( $field->type eq 'Boolean' ) {
$field->render_args->{element_attr}{class} = ['sel_elem'];
}
}
}
apply roles to fields
A role to overide the 'id' attribute. (Note: you can do this is in a built-in way with the 'build_field_id' form method, but this serves as an example.):
package My::DynamicFieldId;
use Moo::Role;
around 'id' => sub {
my $orig = shift;
my $self = shift;
my $form_name = $self->form->name;
return $form_name . "." . $self->full_name;
};
Apply to the fields in an 'after_build_fields' sub.
package My::CustomIdForm2;
use Moo;
use Data::MuForm::Meta;
extends 'Data::MuForm';
has '+name' => ( default => 'D123' );
has_field 'foo';
has_field 'bar';
sub after_build_fields {
my $self = shift;
# the 'index' contains all fields, not just top level fields
foreach my $field ( values %{$self->index} ) {
Role::Tiny->apply_roles_to_object($field, 'My::DynamicFieldId');
}
}
Use an external validation method
The form package has an attribute to hold the coderef which will do the validation, which is called in a validate method.
package SignupForm;
use Moo;
use Data::MuForm::Meta;
extends 'Data::MuForm';
has check_name_availability => ( is => 'ro', required => 1 );
has_field 'name';
has_field 'email';
sub validate {
my $self = shift;
my $name = $self->value->{name};
my $meth = $self->check_name_availability;
if ( defined $name && length $name && !$meth->($name) ) {
$self->field('name')->add_error('That name is taken already');
}
}
1;
A non-form Perl application has a method to validate a field, such as checking in the database that a username is unique:
package MyApp::Signup;
use Moo;
has 'form' => ( is => 'ro', builder => 'build_form' );
sub build_form {
my $self = shift;
return SignupForm->new(
{
check_name_availability => sub {
my $name = shift;
return $self->username_available($name);
},
}
);
}
sub username_available {
my ( $self, $name ) = @_;
return $name eq 'Sam' ? 1 : 0;
}
1;
Order fields from a role
Given a Moo::Role with fields:
package MyApp::Form::Role::MyFields;
use Moo::Role;
use Data::MuForm::Meta;
has_field 'r-one';
has_field 'r-two';
has_field 'r-three';
...And a Form class which includes those fields.
package MyApp::Form::TestRole;
use Moo;
use Data::MuForm::Meta;
extends 'Data::MuForm';
with 'MyApp::Form::Role::MyFields';
has_field 'f-one';
has_field 'f-two';
has_field 'f-three';
has_field 'f-four';
...Order the fields in an 'order_fields' sub in the form.
# put role fields between f-two and f-three
sub order_fields {
my $self = shift;
my @form_order = (1, 2, 6, 7, 8);
my @role_order = (3, 4, 5);
foreach my $field ( $self->all_fields ) {
my $order;
if ( $field->source eq __PACKAGE__ ) {
$order = shift @form_order;
}
else {
$order = shift @role_order;
}
$field->order($order);
}
}
AUTHOR
Gerda Shank
COPYRIGHT AND LICENSE
This software is copyright (c) 2017 by Gerda Shank.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.