The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Form::Tiny::Manual::Cookbook - common advanced tasks with Form::Tiny

RECIPES

Corinna compatibility

Perl core OO system named Corinna (experimental) is not currently compatible with bless-style objects. Since it uses different than hashref storage for its objects, it is unlikely that it will ever be compatible. It is recommended to stick to Moo/se when using Form::Tiny.

Object::Pad compatibility

Object::Pad, the playground for Corinna, can 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/se 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;

SEE ALSO