package HTML::Widget;
use warnings;
use strict;
use base 'HTML::Widget::Accessor';
use HTML::Widget::Result;
use Scalar::Util 'blessed';
use Carp qw/croak/;
# For PAR
use Module::Pluggable::Fast
search =>
[qw/HTML::Widget::Element HTML::Widget::Constraint HTML::Widget::Filter/],
require => 1;
__PACKAGE__->plugins;
__PACKAGE__->mk_accessors(
qw/container indicator query subcontainer uploads strict empty_errors
element_container_class xhtml_strict unwrapped explicit_ids/
);
__PACKAGE__->mk_ro_accessors(qw/implicit_subcontainer/);
# Custom attr_accessor for id provided later
__PACKAGE__->mk_attr_accessors(qw/action enctype method/);
use overload '""' => sub { return shift->attributes->{id} }, fallback => 1;
*const = \&constraint;
*elem = \&element;
*name = \&id;
*tag = \&container;
*subtag = \&subcontainer;
*result = \&process;
*indi = \&indicator;
*constrain_all = \*constraint_all;
our $VERSION = '1.11';
=head1 NAME
HTML::Widget - HTML Widget And Validation Framework
=head1 NOTE
L is no longer under active development and the current
maintainers are instead pursuing an intended replacement (see the
L for details).
Volunteer maintainers / developers for L, please contact
the L.
=head1 SYNOPSIS
use HTML::Widget;
# Create a widget
my $w = HTML::Widget->new('widget')->method('get')->action('/');
# Add a fieldset to contain the elements
my $fs = $w->element( 'Fieldset', 'user' )->legend('User Details');
# Add some elements
$fs->element( 'Textfield', 'age' )->label('Age')->size(3);
$fs->element( 'Textfield', 'name' )->label('Name')->size(60);
$fs->element( 'Submit', 'ok' )->value('OK');
# Add some constraints
$w->constraint( 'Integer', 'age' )->message('No integer.');
$w->constraint( 'Not_Integer', 'name' )->message('Integer.');
$w->constraint( 'All', 'age', 'name' )->message('Missing value.');
# Add some filters
$w->filter('Whitespace');
# Process
my $result = $w->process;
my $result = $w->process($query);
# Check validation results
my @valid_fields = $result->valid;
my $is_valid = $result->valid('foo');
my @invalid_fields = $result->have_errors;
my $is_invalid = $result->has_errors('foo');;
# CGI.pm-compatible! (read-only)
my $value = $result->param('foo');
my @params = $result->param;
# Catalyst::Request-compatible
my $value = $result->params->{foo};
my @params = keys %{ $result->params };
# Merge widgets (constraints and elements will be appended)
$widget->merge($other_widget);
# Embed widgets (as fieldset)
$widget->embed($other_widget);
# Get list of elements
my @elements = $widget->get_elements;
# Get list of constraints
my @constraints = $widget->get_constraints;
# Get list of filters
my @filters = $widget->get_filters;
# Complete xml result
[% result %]
[% result.as_xml %]
# Iterate over elements
# Iterate over validation errors
[% FOREACH element = result.have_errors %]
[% element %]:
[% FOREACH error = result.errors(element) %]
-
[% error.name %]: [% error.message %] ([% error.type %])
[% END %]
[% END %]
[% FOREACH element = result.have_errors %]
[% IF result.error( element, 'Integer' ) %]
- [% element %] has to be an integer.
[% END %]
[% END %]
[% FOREACH error = result.errors %]
[% error.name %]: [% error.message %] ([% error.type %])
[% END %]
# XML output looks like this (easy to theme with css)
=head1 DESCRIPTION
Create easy to maintain HTML widgets!
Everything is optional, use validation only or just generate forms,
you can embed and merge them later.
The API was designed similar to other popular modules like
L and L,
L is also built in (and much faster).
This Module is very powerful, don't misuse it as a template system!
=head1 METHODS
=head2 new
Arguments: $name, \%attributes
Return Value: $widget
Create a new HTML::Widget object. The name parameter will be used as the
id of the form created by the to_xml method.
The C argument is equivalent to using the L
method.
=cut
sub new {
my ( $self, $name, $attrs ) = @_;
$self = bless {}, ( ref $self || $self );
$self->container('form');
$self->subcontainer('fieldset');
$self->name( defined $name ? $name : 'widget' );
if ( defined $attrs ) {
croak 'attributes argument must be a hash-reference'
if ref($attrs) ne 'HASH';
$self->attributes->{$_} = $attrs->{$_} for keys %$attrs;
}
return $self;
}
=head2 action
Arguments: $uri
Return Value: $uri
Get/Set the action associated with the form. The default is no action,
which causes most browsers to submit to the current URI.
=head2 attributes
=head2 attrs
Arguments: %attributes
Arguments: \%attributes
Return Value: $widget
Arguments: none
Return Value: \%attributes
Accepts either a list of key/value pairs, or a hash-ref.
$w->attributes( $key => $value );
$w->attributes( { $key => $value } );
Returns the C<$widget> object, to allow method chaining.
As of v1.10, passing a hash-ref no longer deletes current
attributes, instead the attributes are added to the current attributes
hash.
This means the attributes hash-ref can no longer be emptied using
C<< $w->attributes( { } ); >>. Instead, you may use
C<< %{ $w->attributes } = (); >>.
As a special case, if no arguments are passed, the return value is a
hash-ref of attributes instead of the object reference. This provides
backwards compatability to support:
$w->attributes->{key} = $value;
L is an alias for L.
=head2 container
Arguments: $tag
Return Value: $tag
Get/Set the tag used to contain the XML output when as_xml is called on the
HTML::Widget object.
Defaults to C