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
[% FOREACH element = result.elements %] [% element.field_xml %] [% element.error_xml %] [% END %]
# 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)
    Contains digit characters.
    =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
    . =head2 element_container_class Arguments: $class_name Return Value: $class_name Get/Set the container_class override for all elements in this widget. If set to non-zero value, process will call $element->container_class($class_name) for each element. Defaults to not set. See L. =head2 elem =head2 element Arguments: $type, $name, \%attributes Return Value: $element Add a new element to the Widget. Each element must be given at least a type. The name is used to generate an id attribute on the tag created for the element, and for form-specific elements is used as the name attribute. The returned element object can be used to set further attributes, please see the individual element classes for the methods specific to each one. The C argument is equivalent to using the L method. If the element starts with a name other than C, you can fully qualify the name by using a unary plus: $self->element( "+Fully::Qualified::Name", $name ); The type can be one of the following: =over 4 =item L my $e = $widget->element('Block'); Add a Block element, which by default will be rendered as a C
    . my $e = $widget->element('Block'); $e->type('img'); =item L my $e = $widget->element( 'Button', 'foo' ); $e->value('bar'); Add a button element. my $e = $widget->element( 'Button', 'foo' ); $e->value('bar'); $e->content('arbitrary markup'); $e->type('submit'); Add a button element which uses a C