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

Valiant::HTML::Util::FormTags - HTML Form Tags

SYNOPSIS

    my $view = Valiant::HTML::Util::View->new(aaa => 1,bbb => 2);
    my $tb = Valiant::HTML::Util::FormTags->new(view => $view);

DESCRIPTION

Functions that generate HTML tags, specifically those around HTML forms. Not all HTML tags are in this library, this focuses on things that would be useful for building HTML forms. In general this is a support libary for Valiant::HTML::FormBuilder but there's nothing preventing you from using these stand alone, particularly when you have very complex form layout needs.

Requiers a 'view' or template object that supports methods for created 'safe' strings that are properly marked as safe for HTML display.

ATTRIBUTES

This class has the following initialization attributes

view

Object, Required. This should be an object that provides methods for creating escaped strings for HTML display. Many template systems provide a way to mark strings as safe for display, such as Mojo::Template. You will need to add the following proxy methods to your view / template to adapt it for use in creating safe strings.

raw

given a string return a single tagged object which is marked as safe for display. Do not do any HTML escaping on the string. This is used when you want to pass strings straight to display and that you know is safe. Be careful with this to avoid HTML injection attacks.

safe

given a string return a single tagged object which is marked as safe for display. First HTML escape the string as safe unless its already been done (no double escaping).

safe_concat

Same as safe but instead works an an array of strings (or mix of strings and safe string objects) and concatenates them all into one big safe marked string.

html_escape

Given a string return string that has been HTML escaped.

read_attribute_for_html

Given an attribute name return the value that the view has defined for it.

attribute_exists_for_html

Given an attribute name return true if the view has defined it.

Both raw, safe and safe_concat should return a 'tagged' object which is specific to your view or template system. However this object must 'stringify' to the safe version of the string to be displayed. See Valiant::HTML::SafeString for example API. We use Valiant::HTML::SafeString internally to provide safe escaping if you're view doesn't do automatic escaping, as many older template systems like Template Toolkit.

See Valiant::HTML::Util::View for a simple view object that provides these methods.

INHERITANCE

This class extends Valiant::HTML::Util::TagBuilder and inherits all methods from that class.

METHODS

The following instance methods are supported by this class

button_tag

    $tb->button_tag($content_string, \%attrs)
    $tb->button_tag($content_string)
    $tb->button_tag(\%attrs, \&content_code_block)
    $tb->button_tag(\&content_code_block)

Creates a button element that defines a submit button, reset button or a generic button which can be used in JavaScript, for example. You can use the button tag as a regular submit tag but it isn't supported in legacy browsers. However, the button tag does allow for richer labels such as images and emphasis, so this helper will also accept a block. By default, it will create a button tag with type submit, if type is not given. HTML attribute name defaults to 'Button' if not supplied. Inner content also defaults to 'Button' if not supplied.

checkbox_tag

    $tb->checkbox_tag($name)
    $tb->checkbox_tag($name, $value)
    $tb->checkbox_tag($name, $value, $checked)
    $tb->checkbox_tag($name, \%attrs)
    $tb->checkbox_tag($name, $value, \%attrs)
    $tb->checkbox_tag($name, $value, $checked, \%attrs)

Creates a check box form input tag. id will be generated from $name if not passed in \%attrs. value attribute will default to '1' and the control is unchecked by default.

fieldset_tag

    $tb->fieldset_tag(\%content_block)
    $tb->fieldset_tag(\%attrs, \%content_block)
    $tb->fieldset_tag($legend, \%attrs, \%content_block)
    $tb->fieldset_tag($legend, \%content_block)

Create a fieldset with inner content. Example:

    $tb->fieldset_tag(sub {
      $tb->button_tag('username');
    });

    # <fieldset><button name="button">username</button></fieldset>
  
    $tb->fieldset_tag('Info', sub {
      $tb->button_tag('username');
    });

    # <fieldset><legend>Info</legend><button name="button">username</button></fieldset>

legend_tag

    $tb->legend_tag($legend, \%html_attrs);
    $tb->legend_tag($legend);
    $tb->legend_tag(\%html_attrs, \&content_block);
    $tb->legend_tag(\&content_block);

Create an HTML form legend tag and content. Examples:

    $tb->legend_tag('test', +{class=>'foo'});
    # <legend class="foo">test</legend>

    $tb->legend_tag('test');
    # <legend>test</legend>

    $tb->legend_tag({class=>'foo'}, sub { 'test' });
    # <legend class="foo">test</legend>

    $tb->legend_tag(sub { 'test' });
    # <legend>test</legend>

form_tag

    $tb->form_tag('/signup', \%attrs, \&content)
    $tb->form_tag(\@args, \%attrs, \&content)

Create a form tag with inner content. Example:

    $tb->form_tag('/user', +{ class=>'form' }, sub {
      $tb->checkbox_tag('person[1]username', +{class=>'aaa'});
    });

Produces:

    <form accept-charset="UTF-8" action="/user" class="form" method="POST">
      <input class="aaa" id="person_1username" name="person[1]username" type="checkbox" value="1"/>
    </form>';

In general \%attrs are expected to be HTML attributes. However, the following special attributes are supported:

csrf_token

If set, will use the value given to generate a hidden input tag with the name csrf_token and the value. Example:

    my $csrf_token = "1234567890";
    $tb->form_tag('/user', +{ csrf_token=>$csrf_token }, sub {
      $tb->checkbox_tag('username', +{class=>'aaa'});
    });

Produces:

    <form accept-charset="UTF-8" action="/user" class="form" method="POST">
      <input class="aaa" id="username" name="username" type="checkbox" value="1"/>
      <input name="csrf_token" type="hidden" value="1234567890"/>
    </form>';
tunneled_method

If set, will change any method attribute to POST and add a query parameter to the action URL with the name _method and the value of the method attribute. Example:

    $tb->form_tag('/user', +{ method=>'DELETE', tunneled_method=>1 }, sub {
      $tb->checkbox_tag('username', +{class=>'aaa'});
    });

Produces:

    <form accept-charset="UTF-8" action="/user?_method=DELETE" class="form" method="POST">
      <input class="aaa" id="username" name="username" type="checkbox" value="1"/>
    </form>';

Useful for browsers that don't support PUT or DELETE methods in forms (which is most of them).

These special attributes will be removed from the attributes list before generating the HTML tag.

label_tag

    $tb->label_tag($name, $content, \%attrs);
    $tb->label_tag($name, $content);
    $tb->label_tag($name, \%attrs, \&content);
    $tb->label_tag($name, \&content);

Create a label tag where $name is set to the for attribute. Can contain string or block contents. Label contents default to something based on $name;

    $tb->label_tag('user_name', "User", +{id=>'userlabel'});    # <label id='userlabel' for='user_name'>User</label>
    $tb->label_tag('user_name');                                # <label for='user_name'>User Name</label>

Example with block content:

    $tb->label_tag('user_name', sub {
      'User Name Active',
      $tb->checkbox_tag('active', 'yes', 1);
    });

    <label for='user_name'>
      User Name Active<input checked  value="yes" id="user_name" name="user_name" type="checkbox"/>
    </label>

Produce a label tag, often linked to an input tag. Can accept a block coderef. Examples:

radio_button_tag

    $tb->radio_button_tag($name, $value)
    $tb->radio_button_tag($name, $value, $checked)
    $tb->radio_button_tag($name, $value, $checked, \%attrs)
    $tb->radio_button_tag($name, $value, \%attrs)

Creates a radio button; use groups of radio buttons named the same to allow users to select from a group of options. Examples:

    $tb->radio_button_tag('role', 'admin', 0, +{ class=>'radio' });
    # <input class="radio" id="role_admin" name="role" type="radio" value="admin"/>

    $tb->radio_button_tag('role', 'user', 1, +{ class=>'radio' });
    # <input checked class="radio" id="role_user" name="role" type="radio" value="user"/>'

option_tag

    $tb->option_tag($text, \%attributes)
    $tb->option_tag($text)

Create a single HTML option. value attribute is inferred from $text if not in \%attributes. Examples:

    $tb->option_tag('test', +{class=>'foo', value=>'100'});
    # <option class="foo" value="100">test</option>

    $tb->option_tag('test'):
    #<option value="test">test</option>

text_area_tag

    $tb->text_area_tag($name, \%attrs)
    $tb->text_area_tag($name, $content, \%attrs)

Create a named text_area form field. Examples:

    $tb->text_area_tag("user", "hello", +{ class=>'foo' });
    # <textarea class="foo" id="user" name="user">hello</textarea>

    $tb->text_area_tag("user",  +{ class=>'foo' });
    # <textarea class="foo" id="user" name="user"></textarea>

input_tag

    $tb->input_tag($name, $value, \%attrs)
    $tb->input_tag($name, $value)
    $tb->input_tag($name)
    $tb->input_tag($name, \%attrs)
    $tb->input_tag(\%attrs)

Create a HTML input tag. If $name and/or $value are set, they are used to populate the 'name' and 'value' attributes of the input. Anything passed in the \%attrs hashref overrides. Examples:

    $tb->input_tag('username', 'jjn', +{class=>'aaa'});
    # <input class="aaa" id="username" name="username" type="text" value="jjn"/>

    $tb->input_tag('username', 'jjn');
    # <input id="username" name="username" type="text" value="jjn"/>

    $tb->input_tag('username');
    # <input id="username" name="username" type="text"/>

    $tb->input_tag('username', +{class=>'foo'});
    # <input class="foo" id="username" name="username" type="text"/>

    $tb->input_tag(+{class=>'foo'});
    # <input class="foo" type="text"/>

password_tag

Creates an password input tag with the given type. Example:

    $tb->password_tag('password', +{class=>'foo'});
    # <input class="foo" id="password" name="password" type="password"/>

hidden_tag

Creates an input tag with the given type. Example:

    $tb->hidden_tag('user_id', 100, +{class=>'foo'});
    # <input class="foo" id="user_id" name="user_id" type="hidden" value="100"/>
    

submit_tag

    $tb->submit_tag
    $tb->submit_tag($value)
    $tb->submit_tag(\%attrs)
    $tb->submit_tag \($value, \%attrs)

Create a submit tag. Examples:

    $tb->submit_tag;
    # <input id="commit" name="commit" type="submit" value="Save changes"/>

    $tb->submit_tag('person');
    # <input id="commit" name="commit" type="submit" value="person"/>

    $tb->submit_tag('Save', +{name=>'person'});
    # <input id="person" name="person" type="submit" value="Save"/>

    $tb->submit_tag(+{class=>'person'});
    # <input class="person" id="commit" name="commit" type="submit" value="Save changes"/>

select_tag

    $tb->select_tag($name, $option_tags, \%attrs)
    $tb->select_tag($name, $option_tags)
    $tb->select_tag($name, \%attrs)

Create a select tag group with options. Examples:

    $tb->select_tag("people", raw("<option>David</option>"));
    # <select id="people" name="people"><option>David</option></select>

    $tb->select_tag("people", raw("<option>David</option>"), +{include_blank=>1});
    # <select id="people" name="people"><option label=" " value=""></option><option>David</option></select>

    $tb->select_tag("people", raw("<option>David</option>"), +{include_blank=>'empty'});
    # <select id="people" name="people"><option value="">empty</option><option>David</option></select>
      
    $tb->select_tag("prompt", raw("<option>David-prompt</option>"), +{prompt=>'empty-prompt', class=>'foo'});
    # <select class="foo" id="prompt" name="prompt"><option value="">empty-prompt</option><option>David-prompt</option></select>

options_for_select

    $tb->options_for_select([$value1, $value2, ...], $selected_value)
    $tb->options_for_select([$value1, $value2, ...], \@selected_values)
    $tb->options_for_select([$value1, $value2, ...], +{ selected => $selected_value, disabled => \@disabled_values, %global_options_attributes })
    $tb->options_for_select([ [$label, $value], [$label, $value, \%attrs], ...])

Create a string of HTML option tags suitable for using with select_tag. Accepts two arguments the first of whuch is required. The first argument is an arrayref of values used for the options. Each value can be one of a scalar (in which case the value is used as both the text label for the option as well as its actual value attribute) or a arrayref where the first item is the option label, the second is the value and an option third is a hashref used to add custom attributes to the option.

The second (optional) argument lets you set which options are marked selected and possible disabled If the second argument is a scalar value then it is used to mark that value as selected. If its an arrayref then all matching values are selected. If its a hashref we look for a key selected and key <disabled> and expect those (if exists) to be an arrayref of matching values. Any additional keys in the hash will be passed as global HTML attributes to the options. Examples:

    $tb->options_for_select(['A','B','C']);
    # <option value="A">A</option>
    # <option value="B">B</option>
    # <option value="C">C</option>

    $tb->options_for_select(['A','B','C'], 'B');
    # <option value="A">A</option>
    # <option selected value="B">B</option>
    # <option value="C">C</option>

    $tb->options_for_select(['A','B','C'], ['A', 'C']);
    #<option selected value="A">A</option>
    #<option value="B">B</option>
    #<option selected value="C">C</option>

    $tb->options_for_select(['A','B','C'], ['A', 'C']);
    # <option selected value="A">A</option>
    # <option value="B">B</option>
    # <option selected value="C">C</option>

    $tb->options_for_select([[a=>'A'],[b=>'B'], [c=>'C']]);
    # <option value="A">a</option>
    # <option value="B">b</option>
    # <option value="C">c</option>

    $tb->options_for_select([[a=>'A'],[b=>'B'], [c=>'C']], 'B');
    # <option value="A">a</option>
    # <option selected value="B">b</option>
    # <option value="C">c</option>

    $tb->options_for_select(['A',[b=>'B', {class=>'foo'}], [c=>'C']], ['A','C']);
    # <option selected value="A">A</option>
    # <option class="foo" value="B">b</option>
    # <option selected value="C">c</option>

    $tb->options_for_select(['A','B','C'], +{selected=>['A','C'], disabled=>['B'], class=>'foo'});
    # <option class="foo" selected value="A">A</option>
    # <option class="foo" disabled value="B">B</option>
    # <option class="foo" selected value="C">C</option>

This function is useful with the select_tag:

    $tb->select_tag("state", options_for_select(['A','B','C'], 'A'), +{include_blank=>1});
    # <select id="state" name="state">
    #  <option label=" " value=""></option>
    #  <option selected value="A">A</option>
    #  <option value="B">B</option>
    #  <option value="C">C</option>
    # </select>

Please note that since options_for_select returns a Valiant::HTML::SafeString or safe string object as supported by your view/template system of choice you don't need to add any additional escaping.

options_from_collection_for_select

Given a collection (an object that does the interface defined by Valiant::HTML::Util::Collection return a string of options suitable for select_tag. Optionally you can pass additional arguments, like with options_for_select to mark individual options as selected, disabled and to pass additional HTML attributes. Examples:

    my $collection = Valiant::HTML::Util::Collection->new([label=>'value'], [A=>'a'], [B=>'b'], [C=>'c']);

    $tb->options_from_collection_for_select($collection, 'value', 'label');
    # <option value="value">label</option>
    # <option value="a">A</option>
    # <option value="b">B</option>
    # <option value="c">C</option>

    $tb->options_from_collection_for_select($collection, 'value', 'label', 'a');
    # <option value="value">label</option>
    # <option selected value="a">A</option>
    # <option value="b">B</option>
    # <option value="c">C</option>

    $tb->options_from_collection_for_select($collection, 'value', 'label', ['a', 'c']);
    # <option value="value">label</option>
    # <option selected value="a">A</option>
    # <option value="b">B</option>
    # <option selected value="c">C</option>

    $tb->options_from_collection_for_select($collection, 'value', 'label', +{selected=>['a','c'], disabled=>['b'], class=>'foo'})
    # <option class="foo" value="value">label</option>
    # <option class="foo" selected value="a">A</option>
    # <option class="foo" disabled value="b">B</option>
    # <option class="foo" selected value="c">C</option>

If you have a properly formed array you can use the array_to_collection helper method:

    my $collection = $tb->array_to_collection([label=>'value'], [A=>'a'], [B=>'b'], [C=>'c']);
    $tb->options_from_collection_for_select($collection, 'value', 'label');

Additionally you can pass a coderef for dynamic selecting. Example:

    $tb->options_from_collection_for_select($collection, 'value', 'label', sub { shift->value eq 'a'} );
    # <option value="value">label</option>
    # <option selected value="a">A</option>
    # <option value="b">B</option>
    # <option value="c">C</option>

The collection object must at minimum provide a method next which returns the next object in the collection. This method next should return false when all the item objects have been iterated thru in turn. Optionally you can provide a reset method which will be called to return the collection to the first index.

You can see Valiant::HTML::Util::Collection source for example minimal code.

array_to_collection

Given a array of option labels as described above, create a collection

SEE ALSO

Valiant, Valiant::HTML::FormBuilder

AUTHOR

See Valiant

COPYRIGHT & LICENSE

See Valiant