The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

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.