John Siracusa > Rose-HTML-Objects-0.617 > Rose::HTML::Form

Download:
Rose-HTML-Objects-0.617.tar.gz

Dependencies

Annotate this POD

Website

CPAN RT

New  1
Open  0
View/Report Bugs
Module Version: 0.616   Source   Latest Release: Rose-HTML-Objects-0.621

NAME ^

Rose::HTML::Form - HTML form base class.

SYNOPSIS ^

  package PersonForm;

  use base 'Rose::HTML::Form';

  use Person;

  sub build_form 
  {
    my($self) = shift;

    $self->add_fields
    (
      name  => { type => 'text',  size => 25, required => 1 },
      email => { type => 'email', size => 50, required => 1 },
      phone => { type => 'phone' },
    );
  }

  sub validate
  {
    my($self) = shift;

    # Base class will validate individual fields in isolation,
    # confirming that all required fields are filled in, and that
    # the email address and phone number are formatted correctly.
    my $ok = $self->SUPER::validate(@_);
    return $ok  unless($ok);

    # Inter-field validation goes here
    if($self->field_value('name') ne 'John Doe' &&
       $self->field_value('phone') =~ /^555/)
    {
      $self->error('Only John Doe can have a 555 phone number.');
      return 0;
    }

    return 1;
  }

  sub init_with_person # give a friendlier name to a base-class method
  {
    my($self, $person) = @_;
    $self->init_with_object($person);
  }

  sub person_from_form
  {
    my($self) = shift;

    # Base class method does most of the work
    my $person = $self->object_from_form(class => 'Person');

    # Now fill in the non-obvious details...
    # e.g., set alt phone to be the same as the regular phone
    $person->alt_phone($self->field_value('phone'));

    return $person;
  }

  ...

  #
  # Sample usage in a hypothetical web application
  #

  $form = PersonForm->new;

  if(...)
  {
    # Get query parameters in a hash ref and pass to the form
    my $params = MyWebServer->get_query_params();
    $form->params($params);

    # ...or  initialize form params from a CGI object
    # $form->params_from_cgi($cgi); # $cgi "isa" CGI

    # ...or initialize params from an Apache request object
    # (mod_perl 1 and 2 both supported)
    # $form->params_from_apache($r);

    # Initialize the fields based on params
    $form->init_fields();

    unless($form->validate) 
    {
      return error_page(error => $form->error);
    }

    $person = $form->person_from_form; # $person is a Person object

    do_something_with($person);
    ...
  }
  else
  {
    $person = ...; # Get or create a Person object somehow

    # Initialize the form with the Person object
    $form->init_with_person($person);

    # Pass the initialized form object to the template
    display_page(form => $form);
  }
  ...

DESCRIPTION ^

Rose::HTML::Form is more than just an object representation of the <form> HTML tag. It is meant to be a base class for custom form classes that can be initialized with and return "rich" values such as objects, or collections of objects.

Building up a reusable library of form classes is extremely helpful when building large web applications with forms that may appear in many different places. Similar forms can inherit from a common subclass, and forms may be nested.

This class inherits from, and follows the conventions of, Rose::HTML::Object. Inherited methods that are not overridden will not be documented a second time here. See the Rose::HTML::Object documentation for more information.

OVERVIEW ^

Rose::HTML::Form objects are meant to encapsulate an entire HTML form, including all fields within the form. While individual fields may be queried and manipulated, the intended purpose of this class is to treat the form as a "black box" as much as possible.

For example, instead of asking a form object for the values of the "name", "email", and "phone" fields, the user would ask the form object to return a new "Person" object that encapsulates those values.

Form objects should also accept initialization through the same kinds of objects that they return. Subclasses are encouraged to create methods such as (to use the example described above) init_with_person() and person_from_form() in order to do this. The generic methods init_with_object() and object_from_form() are meant to ease the implementation of such custom methods.

Form objects can also take input through a hash. Each hash key correspond to a field (or subfield) name, and each value is either a scalar or a reference to an array of scalars (for multiple-value fields). This hash of parameters can be queried and manipulated before finally calling init_fields() in order to initialize the fields based on the current state of the parameters.

Compound fields (fields consisting of more than one HTML field, such as a month/day/year date field with separate text fields for each element of the date) may be "addressed" by hash arguments using both top-level names (e.g., "birthday") or by subfield names (e.g., "birthday.month", "birthday.day", "birthday.year"). If the top-level name exists in the hash, then subfield names are ignored. See Rose::HTML::Form::Field::Compound for more information on compound fields.

Each form has a list of field objects. Each field object is stored under a name, which may or may not be the same as the field name, which may or may not be the same as the "name" HTML attribute for any of the HTML tags that make up that field.

Forms are validated by calling validate() on each field object. If any individual field does not validate, then the form is invalid. Inter-field validation is the responsibility of the form object.

HIERARCHY ^

Though Rose::HTML::Form objects may have children just like any other Rose::HTML::Object-derived object, the fields that make up the form are treated like "immutable children" in that they can never be removed using the standard child-related APIs. Instead, the fields exist in the middle of any other children.

Pushing a child adds it after the list of fields. Unshifting a child adds it before the list of fields. Popping or shifting children will pull children through, past the fields, to exit the list of children at either end. In other words, children manipulated using the child object APIs will "flow around" the list of fields.

If a particular field is a group of sibling HTML elements with no real parent HTML element (e.g., a radio button group), then the individual sibling items will be flattened out into the list returned by the children method.

If, on the other hand, a field has a true parent/child relationship (e.g., a select box which contains zero or more options) then the items it contains are not flattened by the children method.

For example, if a form has three fields, a text field, a checkbox group with three checkboxes, and a select box with three options, then the children method will return five objects: the text field object, the three checkboxes objects, and a select box object.

See the hierarchy section of the Rose::HTML::Form::Field documentation for more information about how fields made up of multiple HTML tags are treated with respect to parent/child relationships.

Finally, note that nested forms do not affect the parent/child hierarchy presented by the child-related methods inherited from Rose::HTML::Object since the fields contained in nested forms are flattened out into the field list of parent form, as described in the next section.

NESTED FORMS ^

Each form can have zero or more fields as well as zero or more sub-forms. Since <form> HTML tags cannot be nested, this nesting of form objects appears "flattened" in the external interfaces such as HTML generation or field addressing.

Here's a simple example of a nested form made up of a PersonForm and an AddressForm. (Assume PersonForm is constructed as per the synopsis above, and AddressForm is similar, with street, city, state, and zip code fields.)

    package PersonAddressForm;

    use PersonForm;
    use AddressForm;

    sub build_form
    {
      my($self) = shift;

      $self->add_forms
      (
        person  => PersonForm->new,
        address => AddressForm->new,
      );
    }

Each sub-form is given a name. Sub-field addressing incorporates that name in much the same way as compound field addressing, with dots (".") used to delimit the hierarchy. Here are two different ways to get at the person's email field.

    $form = PersonAddressForm->new;

    # These are equivalent
    $email_field = $form->field('person.email');
    $email_field = $form->form('person')->field('email');

Methods on the sub-forms maybe accessed in a similar manner.

    $person = $form->form('person')->person_from_form();

By default, methods are delegated to sub-forms automatically, so this works too.

    $person = $form->person_from_form();

(See the delegate_to_subforms() method to learn how to alter this behavior.)

Nested forms may have their own fields as well, and the nesting may continue to an arbitrary depth. Here's a form that contains a PersonAddressForm as well as two fields of its own.

    package PersonAddressPetsForm;

    use PersonAddressForm;

    sub build_form
    {
      my($self) = shift;

      $self->add_form(pa => PersonAddressForm->new);

      $self->add_fields
      (
        dog => { type => 'text', size => 30 },
        cat => { type => 'text', size => 30 },
      );
    }

Sub-form and field addressing works as expected. Here are several equivalent ways to get at the person's email field.

    $form = PersonAddressPetsForm->new;

    # These are all equivalent
    $email_field = $form->field('pa.person.email');
    $email_field = $form->form('pa.person')->field('email');
    $email_field = $form->form('pa')->form('person')->field('email');

Sub-form method calls and delegation also works as expected.

    # Call method on the PersonForm, two different ways
    $person = $form->form('pa')->form('person')->person_from_form();
    $person = $form->form('pa.person')->person_from_form();

    # Rely on delegation instead
    $person = $form->form('pa')->person_from_form();
    $person = $form->person_from_form();

Nested forms are a great way to build on top of past work. When combined with traditional subclassing, form generation can be entirely cleansed of duplicated code.

HTML ATTRIBUTES ^

Valid attributes:

    accept
    accept-charset
    accesskey
    action
    class
    dir
    enctype
    id
    lang
    method
    name
    onblur
    onclick
    ondblclick
    onfocus
    onkeydown
    onkeypress
    onkeyup
    onmousedown
    onmousemove
    onmouseout
    onmouseover
    onmouseup
    onreset
    onsubmit
    style
    tabindex
    target
    title
    value
    xml:lang

Required attributes (default values in parentheses):

    action
    enctype (application/x-www-form-urlencoded)
    method  (get)

CLASS METHODS ^

default_recursive_init_fields [BOOL]

Get or set a boolean value that determines the default value of the recursive_init_fields object attribute. The default value is false.

delegate_to_subforms [SETTING]

Get or set the value that determines how (or if) forms of this class delegate unresolved method calls to sub-forms. If a method is called on a form of this class, and that method does not exist in this class or any other class in its inheritance hierarchy, then the method may optionally be delegated to a sub-forms. Valid values for SETTING are:

"0"

A value of "0" (or undef or any other false value) means that no sub-form delegation will be attempted.

"1"

A value of "1" means the same thing as a value of "runtime" (see below).

"compile"

For each unresolved method call, each sub-form is is considered in the order that they are returned from the forms method until one is found that can handle this method. If one is found, then a new proxy method is added to this class that calls the requested method on the sub-form, passing all arguments unmodified. That proxy method is then called.

Subsequent invocations of this method will no longer trigger the search process. Instead, they will be handled by the newly-compiled proxy method. This is more efficient than repeating the sub-form search each time, but it also means that a change in the list of sub-forms could render the newly compiled method useless (e.g., if the sub-form it delegates to is removed).

If no sub-form can handle the method, then a fatal "unknown method" error occurs.

"runtime"

For each unresolved method call, each sub-form is is considered in the order that they are returned from the forms method until one is found that can handle this method. If one is found, then the method is called on that sub-form, passing all arguments unmodified.

Subsequent invocations of this method will trigger the same search process, again looking for a a sub-form that can handle it. This is less efficient than compiling a new proxy method as described in the documentation for the "compile" setting above, but it does mean that any changes in the list of sub-forms will be handled correctly.

If no sub-form can handle the method, then a fatal "unknown method" error occurs.

The default value for SETTING is compile. See the nested forms section for some examples of sub-form delegation.

default_trim_xy_params [BOOL]

Get or set a boolean value that is used as the default value of the trim_xy_params object attribute. The default value is true.

CONSTRUCTOR ^

new PARAMS

Constructs a new Rose::HTML::Form object based on PARAMS, where PARAMS are name/value pairs. Any object method is a valid parameter name.

OBJECT METHODS ^

add_field ARGS

Convenience alias for add_fields().

add_fields ARGS

Add the fields specified by ARGS to the list of fields contained in this form. ARGS may be a list or a reference to an array. Valid formats for elements of ARGS are:

Field objects

If an argument is "isa" Rose::HTML::Form::Field, then it is added to the list of fields, stored under the name returned by the field's name method.

Field name/type pairs

A pair of simple scalars is taken as a field name and type. The class that corresponds to the specified field type is determined by calling the field_type_class method. Then a new object of that class is constructed and added to the form.

Field name/hashref pairs

A simple scalar followed by a reference to a hash it taken as a field name and a collection of object attributes. The referenced hash must contain a value for the type key. The field class that corresponds to the specified field type is determined by calling the field_type_class method. Then a new object of that class is constructed, with the remaining key/value pairs in the hash are passed to the constructor. The completed field object is then added to the form.

Field name/object pairs

A simple scalar followed by an object that "isa" Rose::HTML::Form::Field is stored as-is, under the specified name.

Each field's parent_form is set to the form object. If the field's rank is undefined, it's set to the value of the form's field_rank_counter attribute and the rank counter is incremented.

Adding a field with the same name as an existing sub-form will cause a fatal error.

Examples:

    # Name/hashref pairs
    $form->add_fields(name  => { type => 'text',  size => 20 },
                      email => { type => 'email', size => 30 });

    # Name/type pairs
    $form->add_fields(name  => 'text',
                      email => 'email');

    $name_field = 
      Rose::HTML::Form::Field::Text->new(name => 'name',
                                         size => 25);

    $email_field = 
      Rose::HTML::Form::Field::Text->new(name => 'email',
                                         size => 50);

    # Object arguments
    $form->add_fields($name_field, $email_field);

    # Name/object pairs
    $form->add_fields(name  => $name_field, 
                      email => $email_field);

    # Mixed
    $form->add_fields($name_field, 
                      email => $email_field,
                      nick  => { type => 'text', size => 15 },
                      age   => 'text');
add_field_type_classes [MAP]

Add entries to the field_type_classes hash that maps field type strings to the names of the Rose::HTML::Form::Field-derived classes. Example:

    My::HTML::Form->add_field_type_classes
    (
      nick => 'My::HTML::Form::Field::Nickname',
      age  => 'My::HTML::Form::Field::Age',
      ...
    );

This method is an alias for the add_object_type_classes method inherited from Rose::HTML::Object. It is an inherited hash representing the union of the hashes of all superclasses, minus any keys that are explicitly deleted in the current class.

add_form ARGS

This is an alias for the add_forms() method.

add_forms ARGS

Add the forms specified by ARGS to the list of sub-forms contained in this form. See the nested forms section for more information.

Valid formats for elements of ARGS are:

Form objects

If an argument is "isa" Rose::HTML::Form, then it is added to the list of forms, stored under the name returned by the form's form_name method. Example:

    $a_form = Rose::HTML::Form->new(...);
    $b_form = Rose::HTML::Form->new(...);

    # Object arguments
    $form->add_forms($a_form, $b_form);
Form name/object pairs

A simple scalar followed by an object that "isa" Rose::HTML::Form has its form_name set to the specified name and then is stored under that name.

If the name contains any dots (".") it will be taken as a hierarchical name and the form will be added to the specified sub-form under an unqualified name consisting of the final part of the name.

Examples:

    $a_form = Rose::HTML::Form->new(...);
    $b_form = Rose::HTML::Form->new(...);

    # Name/object pairs
    $form->add_forms(a => $a_form, b => $b_form);

    # Mixed
    $form->add_forms($a_form, b => $b_form);

    # Set nested form from the top-level
    $w_form = Rose::HTML::Form->new(...);
    $x_form = Rose::HTML::Form->new(...);
    $y_form = Rose::HTML::Form->new(...);
    $z_form = Rose::HTML::Form->new(...);

    $w_form->add_form('x' => $x_form);
    $x_form->add_form('y' => $y_form);

    # Add $z_form to $w_form->form('x')->form('y') under the name 'z'
    $w_form->add_form('x.y.z' => $z_form);
Form name/hashref pairs

A simple scalar followed by a reference to a hash containing a specification for a form. Currently, the only kind of form that can be specified this way is a repeatable form, in which case the hash reference is known as a "repeat spec". In order to be correctly detected as a repeat spec, the hash must contain a key named repeatable.

The repeat spec is coerced into a set of name/value pairs that are passed to the Rose::HTML::Form::Repeatable constructor call. The coercion exists to allow shorter, more friendly names to be used in the context of a repeat spec. These names are converted into the names of valid Rose::HTML::Form::Repeatable object methods. The following coercion rules are applied to the repeat spec hash reference:

  • If the value of the repeatable key is reference to a hash, the keys and values of that hash are folded into the repeat spec. Otherwise, if a key named default_count does not exist in the repeat spec, then the value of the repeatable key is used as the value of the default_count parameter.
  • The spec and form_spec parameters are aliases for the prototype_form_spec parameter.
  • The class and form_class parameters are aliases for the prototype_form_class parameter.
  • The form parameter is an alias for the prototype_form parameter.

Here are some example name/hashref pairs suitable for passing as arguments to the add_forms method:

    # Using a form class name
    emails =>
    {
      form_class => 'EmailForm',
      repeatable => 3, # Default count is 3.
    }

    # Using a form class name and form spec
    emails =>
    {
      form_class => 'EmailForm',
      form_spec  => { empty_is_ok => 1 },
      repeatable => 3, # Default count is 3.
    }

    # Using a generic form class and form spec to specify the 
    # contents of a repeated form "inline" in the repeat spec
    nicknames =>
    {
      form_class => 'My::HTML::Form',
      form_spec  => { fields => [ nick => { type => 'text' } ] },
      repeatable => 3, # Default count is 3.
    }

    # Using a prototype object
    nicknames =>
    {
      form          => NickNameForm->new,
      default_count => 0, # Explicitly set default count to 0.
      repeatable    => 1, # This key must be present even though
                          # the default count is set above.
    }

Each form's parent_form is set to the form object it was added to.

Adding a form with the same name as an existing field will cause a fatal error.

add_param_value NAME, VALUE

Add VALUE to the parameter named NAME. Example:

    $form->param(a => 1);
    print $form->param('a'); # 1

    $form->add_param_value(a => 2);

    print join(',', $form->param('a')); # 1,2
app [OBJECT]

Get or set a weakened reference to the application object that "owns" this form.

add_repeatable_form ARGS

This method is an alias for the add_repeatable_forms() method.

add_repeatable_forms ARGS

Add the repeatable forms specified by ARGS to the list of sub-forms contained in this form. This method takes arguments in the same format as the add_forms method, except that all argument types are coerced into a form that will cause add_forms to recognize it as a repeatable form. This is a convenient way to add repeatable forms without having to include the repeatable key in your repeat spec. (See the documentation for the add_forms method for more information.)

Examples

    $form->add_repeatable_forms
    (
      # Object argument
      EmailForm->new(...), 

      # Name/object pair
      colors => ColorForm->new(...),

      # Name/hashref pair. (Note: no "repeatable" key needed)
      nicknames => 
      {
        form          => NickNameForm->new,
        default_count => 2,
      },
    );
build_on_init [BOOL]

Get or set a boolean flag that indicates whether or not build_form() should be called from within the init() method. See build_form() for more information.

build_form

This default implementation of this method is a no-op. It is meant to be overridden by subclasses. It is called at the end of the init() method if build_on_init() is true. (Remember that this class inherits from Rose::HTML::Object, which inherits from Rose::Object, which defines the init() method, which is called from the constructor. See the Rose::Object documentation for more information.)

If build_on_init() is false, then you must remember to call build_form() manually.

Subclasses should populate the field list in their overridden versions of build_form(). Example:

  sub build_form 
  {
    my($self) = shift;

    $self->add_fields
    (
      name  => { type => 'text',  size => 25, required => 1 },
      email => { type => 'email', size => 50, required => 1 },
      phone => { type => 'phone' },
    );
  }
clear

Call clear() on each field object and set error() to undef.

clear_fields

Call clear() on each field object.

coalesce_hidden_fields [BOOL]

Get or set the boolean flag that controls how compound field values are encoded in hidden fields. If this flag is true, then each compound field is encoded as a single hidden field. If the flag is false (the default), then each subfield of a compound field will have its own hidden field.

coalesce_query_string_params [BOOL]

Get or set the boolean flag that controls how compound field values are encoded in the query string. If this flag is true (the default), then compound fields are represented by a single query parameter. Otherwise, the subfields of each compound field appear as separate query parameters.

compare_fields [FIELD1, FIELD2]

Compare two fields, returning 1 if FIELD1 should come before FIELD2, -1 if FIELD2 should come before FIELD1, or 0 if neither field should come before the other. This method is called from within the field_names method to determine the order of the fields in this form.

The default implementation performs a string comparison on the names of the fields.

compare_forms [FORM1, FORM2]

Compare two forms, returning 1 if FORM1 should come before FORM2, -1 if FORM2 should come before FORM1, or 0 if neither form should come before the other. This method is called from within the form_names and field_monikers methods to determine the order of the sub-forms nested within this form.

The default implementation compares the rank of the forms in numeric context.

delete_field NAME

Delete the form stored under the name NAME. If NAME "isa" Rose::HTML::Form::Field, then the name method is called on it and the return value is used as NAME.

delete_fields

Delete all fields, leaving the list of fields empty. The field_rank_counter is also reset to 1.

delete_field_type_class TYPE

Delete the type/class mapping entry for the field type TYPE.

delete_form NAME

Delete the form stored under the name NAME. If NAME "isa" Rose::HTML::Form, then the form_name method is called on it and the return value is used as NAME.

delete_forms

Delete all sub-forms, leaving the list of sub-forms empty.

delete_param NAME [, VALUES]

If just the NAME argument is passed, the parameter named NAME is deleted.

If VALUES are also passed, then VALUES are deleted from the set of values held by the parameter name NAME. If only one value remains, then it is the new value for the NAME parameter (i.e., the value is no longer an array reference, but a scalar instead). If every value is deleted, then the NAME parameter is deleted as well. Example:

    $form->param(a => [ 1, 2, 3, 4 ]);

    $form->delete_param(a => 1);
    $vals = $form->param('a'); # [ 2, 3, 4 ]

    $form->delete_param(a => [ 2, 3 ]);
    $vals = $form->param('a'); # 4

    $form->delete_param(a => 4);
    $vals = $form->param('a'); # undef
    $form->param_exists('a');  # false
delete_params

Delete all parameters.

delete_repeatable_form NAME

Delete the repeatable form stored under the name NAME. If NAME "isa" Rose::HTML::Form, then the form_name method is called on it and the return value is used as NAME.

delete_repeatable_forms

Delete all repeatable sub-forms.

empty_is_ok [BOOL]

Get or set a boolean value that indicates whether or not validate will be allowed to return true if every field in the form is empty, even if some of them are required. The default value is false.

end_html

Returns the HTML required to end the form.

end_xhtml

Returns the XHTML required to end the form.

end_multipart_html

Returns the HTML required to end a multipart form.

end_multipart_xhtml

Returns the XHTML required to end a multipart form.

field NAME [, VALUE]

Get or set the field specified by NAME. If only a NAME argument is passed, then the field stored under the name NAME is returned. If no field exists under that name exists, then undef is returned.

If both NAME and VALUE arguments are passed, then the VALUE must be a Rose::HTML::Form::Field or a reference to a hash whose contents are as described in the documentation for the add_fields method.

fields [FIELDS]

If FIELDS are passed, this method deletes all existing fields and then calls add_fields, passing all arguments.

The return value is an ordered list of this form's field objects in list context, or a reference to this list in scalar context. The order of the fields matches the order of the field names returned by the field_monikers method.

fields_depth_first

Returns a list (in list context) or reference to an array (in scalar context) of this form's field objects ordered according to a depth-first traversal of all sub-forms. Fields within a given form are ordered by rank, and all fields at a given level precede any sub-forms nested under that level.

field_monikers

Returns an ordered list of field monikers in list context, or a reference to this list in scalar context. A "moniker" is a fully qualified name, including any sub-form or sub-field prefixes (e.g., "pa.person.email" as seen in the nested forms section above).

The order is determined by the compare_forms and compare_fields methods. The compare_forms method is passed the parent form of each field. If it returns a true value, then that value is used to sort the two fields being compared. If it returns false, then the compare_fields method is called with the two field objects as arguments and its return value is used to determine the order. See the documentation for the compare_forms and compare_fields methods for more information.

field_names

This method simply calls field_monikers.

field_rank_counter [INT]

Get or set the value of the counter used to set the rank of fields as they're added to the form. The counter starts at 1 by default.

field_type_class TYPE [, CLASS]

Given the field type string TYPE, return the name of the Rose::HTML::Object-derived class mapped to that name. If a CLASS is passed, the field type TYPE is mapped to CLASS.

This method is an alias for the object_type_class method inherited from Rose::HTML::Object. It is an inherited hash representing the union of the hashes of all superclasses, minus any keys that are explicitly deleted in the current class.

field_type_classes [MAP]

Get or set the hash that maps object type strings to the names of the Rose::HTML::Object-derived classes. This map

If passed MAP (a list of type/class pairs or a reference to a hash of the same) then MAP replaces the current field type mapping. Returns a list of type/class pairs (in list context) or a reference to a hash of type/class mappings (in scalar context).

This method is an alias for the object_type_classes method inherited from Rose::HTML::Object. It is an inherited hash representing the union of the hashes of all superclasses, minus any keys that are explicitly deleted in the current class.

The default mapping of type names to classes is shown in the Rose::HTML::Object documentation.

field_value NAME [, VALUE]

If passed NAME and VALUE arguments, then the input_value of the field named NAME is set to VALUE. If passed only a NAME, then the internal_value of the field named NAME is returned. In other words, this:

    $form->field_value(zip_code => '11787');

is equivalent to this:

    $form->field('zip_code')->input_value('11787');

and this:

    $val = $form->field_value('zip_code');

is equivalent to this:

    $val = $form->field('zip_code')->internal_value;

If no field named NAME exists, a fatal error will occur.

form NAME [, OBJECT]

Get or set the sub-form named NAME. If just NAME is passed, the specified sub-form object is returned. If no such sub-form exists, undef is returnend.

If both NAME and OBJECT are passed, a new sub-form is added under NAME.

NAME is a fully-qualified sub-form name. Components of the hierarchy are separated by dots ("."). OBJECT must be an object that inherits from Rose::HTML::Form.

forms [FORMS]

If FORMS are passed, this method deletes all existing forms and then calls add_forms, passing all arguments.

The return value is an ordered list of this form's sub-form objects (if any) in list context, or a reference to this list in scalar context. The order of the forms matches the order of the form names returned by the form_names method.

See the nested forms section to learn more about nested forms.

form_name [NAME]

Get or set the name of this form. This name may or may not have any connection with the value of the "name" HTML attribute on the <form> tag. See the documentation for the name method for details.

form_names

Returns an ordered list of form names in list context, or a reference to this list in scalar context. The order is determined by the compare_forms method. Note that this only lists the forms that are direct children of the current form. Forms that are nested more than one level deep are not listed.

form_rank_counter [INT]

This method is deprecated and will be removed in a future release.

hidden_fields

Returns one or more Rose::HTML::Form::Field::Hidden objects that represent the hidden fields needed to encode all of the field values in this form.

If coalesce_hidden_fields() is true, then each compound field is encoded as a single hidden field. Otherwise, each subfield of a compound field will be have its own hidden field.

html_hidden_fields

Returns the HTML serialization of the fields returned by hidden_fields(), joined by newlines.

init_fields [PARAMS]

Initialize the fields based on params(). In general, this works as you'd expect, but the details are a bit complicated.

The intention of init_fields() is to set field values based solely and entirely on params(). That means that default values for fields should not be considered unless they are explicitly part of params().

In general, default values for fields exist for the purpose of displaying the HTML form with certain items pre-selected or filled in. In a typical usage scenario, those default values will end up in the web browser form submission and, eventually, as as an explicit part of part params(), so they are not really ignored.

But to preserve the intended functionality of init_fields(), the first thing this method does is clear() the form. (This is the default. See the no_clear parameter below.)

If a parameter name exactly matches a field's name (note: the field's name, which is not necessarily the the same as the name that the field is stored under in the form), then the (list context) value of that parameter is passed as the input_value() for that field.

If a field "isa" Rose::HTML::Form::Field::Compound, and if no parameter exactly matches the name of the compound field, then each subfield may be initialized by a parameter name that matches the subfield's name.

If a field is an "on/off" type of field (e.g., a radio button or checkbox), then the field is turned "on" only if the value of the parameter that matches the field's name exactly matches (string comparison) the "value" HTML attribute of the field. If not, and if params_exist(), then the field is set to "off". Otherwise, the field is not modified at all.

PARAMS are name/value pairs. Valid parameters are:

no_clear BOOL

If true, the form is not clear()ed before it is initialized.

recursive BOOL

If true, this method is called recursively on any nested sub-forms. If false, the fields in all nested sub-forms are still initialized as expected, but this is done by iterating over the "flattened" fields list rather than through recursion.

If this parameter is not passed, its value defaults to the value of the recursive_init_fields object attribute.

Examples:

    package RegistrationForm;
    ...
    sub build_form 
    {
      my($self) = shift;

      $self->add_fields
      (
        name => { type => 'text', size => 25 },

        gender => 
        {
          type    => 'radio group',
          choices => { 'm' => 'Male', 'f' => 'Female' },
          default => 'm'
        },

        hobbies =>
        {
          type    => 'checkbox group',
          name    => 'hobbies',
          choices => [ 'Chess', 'Checkers', 'Knitting' ],
          default => 'Chess'
        },

        bday = => { type => 'date split mdy' }
      );
    }

    ...

    $form = RegistrationForm->new();

    $form->params(name    => 'John', 
                  gender  => 'm',
                  hobbies => undef,
                  bday    => '1/24/1984');

    # John, Male, no hobbies, 1/24/1984
    $form->init_fields;

    $form->reset;
    $form->params(name  => 'John', 
                  bday  => '1/24/1984');

    # No name, Male, Chess, 1/24/1984
    $form->init_fields(no_clear => 1);

    $form->reset;
    # Set using subfield names for "bday" compound field
    $form->params('name'       => 'John',
                  'bday.month' => 1,
                  'bday.day'   => 24,
                  'bday.year'  => 1984);

    # John, Male, no hobbies, 1/24/1984
    $form->init_fields();

    $form->reset;
    $form->params('bday'       => '1/24/1984',
                  'bday.month' => 12,
                  'bday.day'   => 25,
                  'bday.year'  => 1975);

    # No name, no gender, no hobbies, but 1/24/1984 because
    # the "bday" param trumps any and all subfield params.
    $form->init_fields();

    $form->reset;

    # Explicitly set hobbies field to Knitting...
    $form->field('hobbies')->input_value('Knitting');

    # ...but then provide a hobbies param with no value
    $form->params('hobbies' => undef);

    # Fields are not cleared, but the existence of the hobbies
    # param with an empty value causes the hobbies list to be
    # empty, instead of the default Chess.  Thus:
    #
    # No name, Male, no hobbies, no birthday
    $form->init_fields(no_clear => 1);
init_fields_with_cgi CGI [, ARGS]

This method is a shortcut for initializing the form's params with a CGI object and then calling init_fields. The CGI argument is passed to the params_from_cgi method and ARGS are passed to the init_fields method.

For example, this:

    $form->init_fields_with_cgi($cgi, no_clear => 1);

Is equivalent to this:

    $form->params_from_cgi($cgi);
    $form->init_fields(no_clear => 1);

See the documentation for the params_from_cgi and init_fields methods for more information.

init_fields_with_apache APR [, ARGS]

This method is a shortcut for initializing the form's params with an apache request object and then calling init_fields. The APR argument is passed to the params_from_apache method and ARGS are passed to the init_fields method.

For example, this:

    $form->init_fields_with_apache($r, no_clear => 1);

Is equivalent to this:

    $form->params_from_apache($r);
    $form->init_fields(no_clear => 1);

See the documentation for the params_from_apache and init_fields methods for more information.

init_with_object OBJECT

Initialize the form based on OBJECT. First, the form is clear()ed. Next, for each field name(), if the object has a method with the same name, then the return value of that method (called in scalar context) is passed as the input_value() for the form field of the same name.

The actual code for the init_with_object() method may be more clear than the description above. Essentially, it does this:

    sub init_with_object
    {
      my($self, $object) = @_;

      $self->clear();

      foreach my $field ($self->fields)
      {
        my $name = $field->local_name;

        if($object->can($name))
        {
          $field->input_value(scalar $object->$name());
        }
      }
    }

Use this method as a "helper" when writing your own methods such as init_with_person(), as described in the example in the overview. init_with_object() should be called in the code for subclasses of Rose::HTML::Form, but never by an end-user of such classes.

The convention for naming such methods is "init_with_foo", where "foo" is a (lowercase, underscore-separated, please) description of the object (or objects) used to initialize the form. You are free to accept and handle any kind or number of arguments in your "init_with_foo()"-style methods (all which you'll carefully document, of course).

The field names may not match up exactly with the object method names. In such cases, you can use init_with_object() to handle all the fields that do match up with method names, and then handle the others manually. Example:

    sub init_with_person 
    {
      my($self, $person) = @_;

      # Handle field names that match method names
      $self->init_with_object($person); 

      # Manually set the non-matching or other fields
      $self->field('phone2')->input_value($person->alt_phone);
      $self->field('is_new')->input_value(1);
      ...
    }
is_empty

Returns true if each field and nested form in this form is_empty(), false otherwise.

is_repeatable

Returns true if this form is a repeatable form, false otherwise.

local_field NAME [, VALUE]

Get or set a field that is an immediate child of the current form. That is, it does not belong to a nested form. If the field specified by NAME does not meet these criteria, then undef is returned. In all other respects, this method behaves like the field method.

Note that NAME should be the name as seen from the perspective of the form object upon which this method is called. So a nested form can always address its local fields using their "short" (unqualified) names even if the form is actually nested within another form.

local_fields

Returns a list of fields that are immediate children of the current form (i.e., fields that do not belong to a nested form).

local_form NAME [, OBJECT]

Get or set a form that is an immediate child of the current form. That is, it does not belong to a nested form. If the form specified by NAME does not meet these criteria, then undef is returned. In all other respects, this method behaves like the form method.

Note that NAME should be the name as seen from the perspective of the form object upon which this method is called. So a nested form can always address its local sub-forms using their "short" (unqualified) names even if the parent form itself is actually nested within another form.

name [NAME]

If passed a NAME argument, then the "name" HTML attribute is set to NAME.

If called without any arguments, and if the "name" HTML attribute is empty, then the "name" HTML attribute is set to the form_name.

Returns the value of the "name" HTML attribute.

object_from_form OBJECT | CLASS | PARAMS

Returns an object built based on the contents of the form.

For each field name(), if the object has a method with the same name, then the internal_value() of the field is passed to the object method of that name. The actual code is almost as simple as this:

  foreach my $field ($self->fields)
  {
    my $name = $field->local_name;

    if($object->can($name))
    {
      $object->$name($field->internal_value);
    }
  }

The only wrinkle is the case where a sub-form and a parent form have fields with the same local_name. In that case, the field "closer" to the "root" form (in terms of the parent/child relationship tree) takes precedence. For example, consider the following fields:

    name
    vendor.name
    vendor.country.name

The local_name for all of these fields is name, but object_from_form will pass the value of the name field to the name() method of the object. See the nested forms section of the documentation for more information on nested forms.

In order to return an object based on a form, object_from_form needs an object. If passed an OBJECT argument, then that's the object that's used. If passed a CLASS name, then a new object is constructed by calling new() on that class. OBJECT or CLASS may alternately be passed as a name/value pair in PARAMS.

Use this method as a "helper" when writing your own methods such as person_from_form(), as described in the example in the overview. object_from_form() should be called in the code for subclasses of Rose::HTML::Form, but never by an end-user of such classes.

The convention for naming such methods is "foo_from_form", where "foo" is a (lowercase, underscore-separated, please) description of the object constructed based on the values in the form's fields.

The field names may not match up exactly with the object method names. In such cases, you can use object_from_form() to handle all the fields that do match up with method names, and then handle the others manually. Example:

  sub person_from_form
  {
    my($self) = shift;

    my $person = $self->object_from_form(class => 'Person');

    $person->alt_phone($self->field('phone2')->internal_value);
    ...
    return $person;
  }

It is the caller's responsibility to ensure that the object class (Person in the example above) is loaded prior to calling this method.

param NAME [, VALUE]

Get or set the value of a named parameter. If just NAME is passed, then the value of the parameter of that name is returned. If VALUE is also passed, then the parameter value is set and then returned.

If a parameter has multiple values, the values are returned as a reference to an array in scalar context, or as a list in list context. Multiple values are set by passing a VALUE that is a reference to an array of scalars.

Failure to pass at least a NAME argument results in a fatal error.

params [PARAMS]

Get or set all parameters at once.

PARAMS can be a reference to a hash or a list of name/value pairs. If a parameter has multiple values, those values should be provided in the form of a reference to an array of scalar values. If the list of name/value pairs has an odd number of items, a fatal error occurs.

If PARAMS is a reference to a hash, then it is accepted as-is. That is, no copying of values is done; the actual hash references is stored. If PARAMS is a list of name/value pairs, then a deep copy is made during assignment.

Regardless of the arguments, this method returns the complete set of parameters in the form of a hash (in list context) or a reference to a hash (in scalar context).

In scalar context, the hash reference returned is a reference to the actual hash used to store parameter names and values in the object. It should be treated as read-only.

The hash returned in list context is a deep copy of the actual hash used to store parameter names and values in the object. It may be treated as read/write.

params_exist

Returns true if any parameters exist, false otherwise.

param_exists NAME

Returns true if a parameter named NAME exists, false otherwise.

param_exists_for_field [ NAME | FIELD ]

Returns true if a param exists that addresses the field named NAME or the Rose::HTML::Form::Field-derived object FIELD, false otherwise.

This method is useful for determining if any query parameters exist that address a compound field. For example, a compound field named a.b.c.d could be addressed by any one of the following query parameters: a, a.b, a.b.c, or a.b.c.d. This method also works with fields inside sub-form. Examples:

    $form = Rose::HTML::Form->new;
    $form->add_field(when => { type => 'datetime split mdyhms' });

    $form->params({ 'when.date' => '2004-01-02' });

    $form->param_exists_for_field('when');            # true
    $form->param_exists_for_field('when.date');       # true
    $form->param_exists_for_field('when.date.month'); # true
    $form->param_exists_for_field('when.time.hour');  # false

    $subform = Rose::HTML::Form->new;
    $subform->add_field(subwhen => { type => 'datetime split mdyhms' });
    $form->add_form(subform => $subform);

    $form->params({ 'subform.subwhen.date' => '2004-01-02' });

    $form->param_exists_for_field('subform.subwhen');            # true
    $form->param_exists_for_field('subform.subwhen.date');       # true
    $form->param_exists_for_field('subform.subwhen.date.month'); # true
    $form->param_exists_for_field('subform.subwhen.time.hour');  # false

    $form->param_exists_for_field('when');            # false
    $form->param_exists_for_field('when.date');       # false
    $form->param_exists_for_field('when.date.month'); # false
    $form->param_exists_for_field('when.time.hour');  # false
params_from_apache APR

Set params by extracting parameter names and values from an apache request object. Calling this method entirely replaces the previous params.

If running under mod_perl 1.x, the APR argument may be:

If running under mod_perl 2.x, the APR may be:

In all cases, APR may be an object that has a param() method that behaves in the following way:

  • When called in list context with no arguments, it returns a list of parameter names.
  • When called in list context with a single parameter name argument, it returns a list of values for that parameter.
params_from_cgi CGI

Set params by extracting parameter names and values from a CGI object. Calling this method entirely replaces the previous params. The CGI argument must be either a CGI object or must have a param() method that behaves in the following way:

  • When called in list context with no arguments, it returns a list of parameter names.
  • When called in list context with a single parameter name argument, it returns a list of values for that parameter.
param_value_exists NAME, VALUE

Determines if a parameter of a particular name exists and has a particular value. This method returns true if the parameter named NAME exists and also has a value that is equal to (string comparison) VALUE. Otherwise, it returns false.

A fatal error occurs unless both NAME and VALUE arguments are passed.

parent_form [FORM]

Get or set the parent form, if any. The reference to the parent form is "weakened" using Scalar::Util::weaken() in order to avoid memory leaks caused by circular references.

prepare [PARAMS]

Prepare the form by calling the prepare method on each field, passing all arguments. This same method is also called for each sub-form, passing all arguments plus the form_only parameter with a true value.

PARAMS are name/value pairs. Valid parameters are:

form_only BOOL

If true, the prepare method is not called for each field.

query_string

Returns a URI-escaped (but not HTML-escaped) query string that corresponds to the current state of the form. If coalesce_query_string_params() is true (which is the default), then compound fields are represented by a single query parameter. Otherwise, the subfields of each compound field appear as separate query parameters.

rank [INT]

Get or set the form's rank. This value can be used for any purpose that suits you, but by default it's used by the compare_forms method to sort sub-forms.

recursive_init_fields [BOOL]

Get or set a boolean value indicating the default value of the <recursive> parameter to the init_fields method. This attribute, in turn, defaults to the value returned by the default_recursive_init_fields class method.

repeatable_form NAME [, OBJECT]

Get or set the repeatable sub-form named NAME. If just NAME is passed, the specified repeatable sub-form object is returned. If no such repeatable sub-form exists, undef is returnend.

If both NAME and OBJECT are passed, a new repeatable sub-form is added under NAME.

NAME is a fully-qualified sub-form name. Components of the hierarchy are separated by dots ("."). OBJECT must be an object that inherits from Rose::HTML::Form::Repeatable.

repeatable_forms [FORMS]

If FORMS are passed, this method deletes all existing repeatable forms and then calls add_repeatable_forms, passing all arguments.

The return value is an ordered list of this form's repeatable sub-form objects (if any) in list context, or a reference to this list in scalar context. The order of the forms matches the order of the form names returned by the form_names method.

See the nested forms section to learn more about nested forms, and the Rose::HTML::Form::Repeatable documentation to learn more about repeatable forms.

reset

Call reset() on each field object and set error() to undef.

reset_fields

Call reset() on each field object.

self_uri

Returns a Rose::URI object corresponding to the current state of the form. If uri_base() is set, then it is included in front of what would otherwise be the start of the URI (i.e., the value of the form's "action" HTML attribute).

start_html

Returns the HTML that will begin the form tag.

start_xhtml

Returns the XHTML that will begin the form tag.

start_multipart_html

Sets the "enctype" HTML attribute to "multipart/form-data", then returns the HTML that will begin the form tag.

start_multipart_xhtml

Sets the "enctype" HTML attribute to "multipart/form-data", then returns the XHTML that will begin the form tag.

trim_xy_params [BOOL]

Get or set a boolean value that determines whether or not params that end in ".x" or ".y" have that suffix trimmed off. This is useful for handling query parameters created by some web browsers in response to clicks on image buttons and other image-based elements. Setting this attribute will propagate the value down to all sub-forms.

The default value is the value returned by the default_trim_xy_params class method.

uri_base [STRING]

Get or set the URI of the form, minus the value of the "action" HTML attribute. Although the form action can be a relative URI, I suggest that it be an absolute path at the very least, leaving the uri_base() to be the initial part of the full URI returned by self_uri(). Example:

    $form->action('/foo/bar');
    $form->uri_base('http://www.foo.com');

    # http://www.foo.com/foo/bar
    $uri = $form->self_uri;
uri_separator [CHAR]

Get or set the character used to separate parameter name/value pairs in the return value of query_string() (which is in turn used to construct the return value of self_uri()). The default is "&".

validate [PARAMS]

Validate the form by calling validate() on each field and validate() on each each sub-form. If any field or form returns false from its validate() method call, then this method returns false. Otherwise, it returns true.

If this method is about to return false and the error attribute of this form is not set, then it is set to a generic error message.

PARAMS are name/value pairs. Valid parameters are:

cascade BOOL

If true, then the validate() method of each sub-form is called, passing PARAMS, with a form_only parameter set to true. The default value of the cascade parameter is true. Note that all fields in all nested forms are validated regardless of the value of this parameter.

form_only BOOL

If true, then the validate method is not called on the fields of this form and its sub-forms. Defaults to false, but is set to true when calling validate() on sub-forms in response to the cascade parameter.

Examples:

    $form = Rose::HTML::Form->new;
    $form->add_field(foo => { type => 'text' });

    $subform = Rose::HTML::Form->new;
    $subform->add_field(bar => { type => 'text' });

    $form->add_form(sub => $subform);

    # Call validate() on fields "foo" and "sub.bar" and
    # call validate(form_only => 1) on the sub-form "sub"
    $form->validate;

    # Same as above
    $form->validate(cascade => 1);

    # Call validate() on fields "foo" and "sub.bar"
    $form->validate(cascade => 0);

    # Call validate(form_only => 1) on the sub-form "sub"
    $form->validate(form_only => 1);

    # Don't call validate() on any fields or sub-forms
    $form->validate(form_only => 1, cascade => 0);
validate_field_html_attrs [BOOL]

Get or set a boolean flag that indicates whether or not the fields of this form will validate their HTML attributes. If a BOOL argument is passed, then it is passed as the argument to a call to validate_html_attrs() on each field. In either case, the current value of this flag is returned.

was_submitted

Returns true id params exist for any field, false otherwise.

xhtml_hidden_fields

Returns the XHTML serialization of the fields returned by hidden_fields(), joined by newlines.

SUPPORT ^

Any Rose::HTML::Objects questions or problems can be posted to the Rose::HTML::Objects mailing list. To subscribe to the list or search the archives, go here:

http://groups.google.com/group/rose-html-objects

Although the mailing list is the preferred support mechanism, you can also email the author (see below) or file bugs using the CPAN bug tracking system:

http://rt.cpan.org/NoAuth/Bugs.html?Dist=Rose-HTML-Objects

There's also a wiki and other resources linked from the Rose project home page:

http://rose.googlecode.com

AUTHOR ^

John C. Siracusa (siracusa@gmail.com)

LICENSE ^

Copyright (c) 2010 by John C. Siracusa. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

syntax highlighting: