NAME
Form::Tiny::Manual::Cookbook - common advanced tasks with Form::Tiny
RECIPES
Corinna compatibility
Future Perl core object orientation system named Corinna, currently implemented in Object::Pad, can also be used together with Form::Tiny:
use Object::Pad;
class ParentForm :repr(HASH)
{
use Form::Tiny -nomoo;
form_field 'f1';
}
class ChildForm isa ParentForm :repr(HASH)
{
use Form::Tiny -nomoo;
form_field 'f2';
}
You must use :repr(HASH)
on the class for it to be able to store Moo properties, as well as use -nomoo
flag in Form::Tiny import. Other than that, it should work the same as with any other OO system.
Mixing form fields with class fields
It is possible and often very helpful to have both form and class fields inside the same form class:
use Form::Tiny;
use Types::Standard qw(Str);
has 'user' => (
is => 'rw',
);
form_field 'username' => (
type => Str,
required => 1,
);
form_field 'password' => (
type => Str,
required => 1,
);
form_cleaner sub {
my ($self, $data) = @_;
# load user from the storage service using $data->{username}
my $user = ...;
if ($user->validate_password($data->{password})) {
# set the user for the class, will be available after validation
$self->user($user);
}
else {
$self->add_error(password => 'invalid password');
}
};
While doing so, make sure not to override any of the Form::Tiny::Form symbols (Moo / Moose should complain about it when it happens).
I18N
Form::Tiny has no system for internationalization. That being said, it makes any custom error messages for fields possible with the message
argument to form_field
. You can translate your messages there:
form_field 'translated' => (
type => SomeType,
message => do_translate('That value is no good'),
);
For a bit more roboust solution, you can include untranslated strings in message
and translate errors in after_error
hook:
form_field 'translated_later' => (
type => SomeType,
message => 'That value is no good',
);
form_hook after_error => (
my ($self, $error) = @_;
$error->set_error(
do_translate($error->error)
);
);
This will also translate any error you add manually in other hooks.
Creating a role plugin
It is possible to create a single package plugin that will mix in a role into the form class:
package Form::Tiny::Plugin::MyRolePlugin;
use strict;
use warnings;
use parent 'Form::Tiny::Plugin';
sub plugin
{
my ($self, $caller, $context) = @_;
return {
roles => [__PACKAGE__],
}
}
use Moo::Role;
sub some_method
{
...
}
1;
The late import of Moo::Role prevents the plugin
method from being mixed in along with some_method
.
Empty forms
Form::Tiny tries hard not to force you to finalize building your form like Moose does with make_immutable
. Form definition is built incrementally with each DSL call. One limitation of this is that if your form contains nothing, there's no place to process plugins and inheritance.
In rare occasions where you actually want to have an empty form, you have to call form_meta
method on the package before going out of scope, for example:
package ChildForm;
use Form::Tiny;
extends 'ParentForm';
__PACKAGE__->form_meta;