A Mason component to fill-in error messages
How often have you seen those sites with a form, and after you miss a field, it pops up a little message in red under the text box indicating what went wrong? I'm guessing a lot, and when writing web applications this can be a pain to code in.
Typically in Perl/PHP, you'd add this by going through your form, adding little bits of code under each and every form element to display the error on invalid input. I quickly got tired of this, and decided to simplify the process.
In examining HTML::FillInForm, I noticed I needed a slightly different tool to easily parse the HTML form. After a little bit of shopping about, I decided on HTML::Parser to do the heavy lifting. Here's a snippet from a Mason page using my error_fill.mas component to toss in the error messages:
% if ($form_status eq 'errors') {
<&| /lib/error_fill.mas, errors => $errors_hash_ref &>
<p style="color: red; font-weight:bold;">Errors Found: Please correct the fields indicated.
<& /forms/myform.mas, %ARGS &>
</&>
% } else {
<& /forms/myform.mas, %ARGS &>
% }
$errors_hash_ref is a hash ref that is keyed by the form field name, with the value set to the error message you want displayed. Right now, error_fill.mas does not have custom pre/post-fix variables for you to tweak how the error message is inserted. It currently puts a <br> followed by a red span element containing your message.
myform.mas is the form I want to display, I prefer to split sections out in Mason to keep my web application modular and the sections of my pages more reusable.
Here's error_fill.mas:
$errors%args>$errors is a hash reference keyed as:
'field name' > 'Error message'
use HTML::Parser;my $form = $m->content;
my $p = HTML::Parser->new(api_version > 3);$p->handler(default => sub { print _ }, "text");
$p->handler(end => sub {
my ($tagname, $text, $attr) = _;
if (($tagname eq ‘select') && (exists $errors->{$attr->{name}})) {
print $text;
print ‘’;
foreach my $err (@{$errors->{$attr->{name}}}) {
print ‘’.$err;
}
print ‘’;
} else {
print $text;
}
},
“tagname, text, attr”);
$p->handler(start => sub {
my ($tagname, $text, $attr) = _;
if (($tagname eq 'input') && (exists $errors->{$attr->{name}})) {
print $text;
print '<span style="color:red;">';
foreach my $err ({$errors->{$attr->{name}}}) {
print ‘’.$err;
}
print ”;
} else {
print $text;
}
},
“tagname, text, attr”);
$p->parse($form);
%init>
Hopefully this will help some people out.