NAME
HTML::FormBuilder::Validation - An extension of the Form object, to allow for javascript-side validation of inputs and also server-side validation after the form is POSTed
SYNOPSIS
First, create the Form object. The keys in the HASH reference is the attributes of the form.
# Form attributes require to create new form object
my $form_attributes =
{
'name' => 'name_test_form',
'id' => 'id_test_form',
'method' => 'post',
'action' => "http://www.domain.com/contact.cgi",
'class' => 'formObject',
};
my $form_obj = new HTML::FormBuilder::Validation(data => $form_attributes);
my $fieldset = $form_obj->add_fieldset({});
Create the input fields with validation
This is quite similar to creating input field in Form object. Likewise you can add validation to HASH reference as the attribute of input field.
Below you can see the sample included four types of validation:
1. regexp: Just write the reqular expression that should be apply to the value
2. min_amount: Needs both type=min_amount and also minimum amount that declared in amount
3. max_amount: Just like min_amount
4. checkbox_checked: Ensure checkbox is checked by user
5. custom: Just the javascript function call with parameters should be given to. It only specifies client side validation.
my $input_field_amount =
{
'label' =>
{
'text' => 'Amount',
'for' => 'amount',
'optional' => '0',
},
'input' =>
{
'type' => 'text',
'id' => 'amount',
'name' => 'amount',
'maxlength' => 40,
'value' => '',
},
'error' =>
{
'text' => '',
'id' => 'error_amount',
'class' => 'errorfield',
},
'validation' =>
[
{
'type' => 'regexp',
'regexp' => '\w+',
'err_msg' => 'Not empty',
},
{
'type' => 'regexp',
'regexp' => '\d+',
'err_msg' => 'Must be digit',
},
{
'type' => 'min_amount',
'amount' => 50,
'err_msg' => 'Too little',
},
{
'type' => 'max_amount',
'amount' => 500,
'err_msg' => 'Too much',
},
{
'type' => 'custom',
'function' => 'custom_amount_validation()',
'err_msg' => 'It is not good',
},
],
};
my $terms_and_condition_checkbox =
{
'label' =>
{
'text' => 'I have read & agree to the terms & condition of the site',
'for' => 'tnc',
},
'input' =>
{
'type' => 'checkbox',
'id' => 'tnc',
'name' => 'tnc',
'value' => '1', # optional
},
'error' =>
{
'id' => 'error_tnc',
'class' => 'errorfield',
},
'validation' =>
[
{
'type' => 'checkbox_checked',
'err_msg' => 'In order to proceed, you need to agree to the terms & condition',
},
],
};
Below is another example with two different fields. In this matter we need to indicate the id of each field in validation attributes.
my $select_curr =
{
'id' => 'select_text_curr',
'name' => 'select_text_curr',
'type' => 'select',
'options' => '<option value=""></option><option value="USD">USD</option><option value="EUR">EUR</option>',
};
my $input_amount =
{
'id' => 'select_text_amount',
'name' => 'select_text_amount',
'type' => 'text',
'value' => ''
};
my $input_field_select_text =
{
'label' =>
{
'text' => 'select_text',
'for' => 'select_text',
},
'input' => [ $select_curr, $input_amount ],
'error' =>
{
'text' => '',
'id' => 'error_select_text',
'class' => 'errorfield',
},
'validation' =>
[
{
'type' => 'regexp',
'id' => 'select_text_curr',
'regexp' => '\w+',
'err_msg' => 'Must be select',
},
{
'type' => 'regexp',
'id' => 'select_text_amount',
'regexp' => '\d+',
'err_msg' => 'Must be digits',
},
{
'type' => 'min_amount',
'id' => 'select_text_amount',
'amount' => 50,
'err_msg' => 'Too little',
},
],
};
my $general_error_field =
{
'error' =>
{
'text' => '',
'id' => 'error_general',
'class' => 'errorfield'
},
};
Adding input fields to form object
Here is just add fields to the form object like before.
$form_obj->add_field($fieldset_index, $general_error_field);
$form_obj->add_field($fieldset_index, $input_field_amount);
$form_obj->add_field($fieldset_index, $input_field_select_text);
Define Javascript code to be run, during onsubmit input validation error
This javascript code will be run before onsubmit return false
$form_obj->onsubmit_js_error("\$('#residence').attr('disabled', true);");
$form_obj->onsubmit_js_error('onsubmit_error_disable_fields()');
Custom javascript validation
Custom javascript validation should be defined and assigned to the form object. Note that, the name and parameters should be the same as the way you indicate function call in validation attributes.
You can see a sample below:
my $custom_javascript = qq~
function custom_amount_validation()
{
var input_amount = document.getElementById('amount');
if (input_amount.value == 100)
{
return false;
}
return true;
}~;
Custom server side validation
The custom server side validation is quite similar to javascript. A reference to a subrotine should be pass to form object.
my $custom_server_side_sub_ref = sub {
if ($form_obj->get_field_value('name') eq 'felix')
{
$form_obj->set_field_error_message('name', 'felix is not allow to use this page');
$form_obj->set_field_error_message('error_general', 'There is an error !!!');
}
};
$form_obj->set_server_side_checks($custom_server_side_sub_ref);
Use form object in cgi files
Somewhere in cgi files you can just print the result of build().
print $form_obj->build();
In submit you need to fill form values, use set_input_fields(\%input) and pass %input HASH and then show what ever you want in result of validation. Just like below:
if (not $form_obj->validate())
{
print '<h1>Test Form</h1>';
print $form_obj->build();
}
else
{
print '<h1>Success !!!</h1>';
}
code_exit();
Attributes
has_error_of
The tag that error happened during validation
custom_server_side_check_of
The custom server side subroutine that will be run on server side.
onsubmit_js_error
javasript code to run during onsubmit error by javasript validation
METHODS
set_input_fields
$form_validation_obj->set_input_fields({username => $username});
assign value to the input fields
validate
$form_validation_obj->validate();
validate form input and return true or false
is_error_found_in
$form_validation_obj->is_error_found_in($input_element_id);
check the erorr is founded in the input element or not
get_has_error
set_field_error_message
set_server_side_checks
validate_csrf
CROSS SITE REQUEST FORGERY PROTECTION
for plain CGI or other framework, read Dancer example below.
CSRF and Dancer
create form HTML and store csrftoken in session
my $form = HTML::FormBuilder::Validation->new(data => $form_attributes, csrftoken => 1); ... my $html = $form->build; # save csrf token in session or cookie session(__csrftoken => $form->csrftoken);
validate csrftoken on form submit
my $csrftoken = session('__csrftoken'); my $form = HTML::FormBuilder::Validation->new(data => $form_attributes, csrftoken => $csrftoken); $form->validate_csrf() or die 'CSRF failed.'; # or call if ( $form->validate() ) { # it calls validate_csrf inside # Yap! it's ok } else { # NOTE we do not have error for csrf on form HTML build # show form again with $form->build }
CSRF and Mojolicious
if you're using Mojolicious and have DefaultHelpers plugin enabled, it's simple to add csrftoken in Validation->new as below:
my $form = HTML::FormBuilder::Validation->new(data => $form_attributes, csrftoken => $c->csrf_token);
Mojolicious $c->csrf_token will handle the session part for you.
AUTHOR
Chylli mailto:chylli@binary.com
INHERITED METHODS
- HTML::FormBuilder
-
BUILDARGS, add_field, add_fieldset, after_form, build_confirmation_button_with_all_inputs_hidden, csrftoken, data, fieldsets, get_field_error_message, get_field_value, set_field_value
- HTML::FormBuilder::Base
- Moo::Object
CONTRIBUTOR
Fayland Lam mailto:fayland@binary.com
Tee Shuwn Yuan mailto:shuwnyuan@binary.com