Sep 10, 2014

Japanese form - confirm - complete flow in Perl

I use the same view as both form and validation.
The trick here is to use multiple submit buttons to determine whether the form is confirmed or not.

The sample is written in Perl with module HTML::Template, however, the idea is open for all server side languages (Java, PHP, Python, ...)

Processing Perl script:
my $query = CGI->new;

    # Flag to display form inputs or not
    my $input = 1;
    if ($ENV{'REQUEST_METHOD'} eq 'POST') {
        if (validate_form()) {
            if ($query->param('submit_confirm') || $query->param('submit_confirm.x')) {
                # Confirmed, end here
                send_email();
                print $query->redirect('complete.pl');
                exit 0;
            }
            if ($query->param('submit_edit') || $query->param('submit_edit.x')) {
                $input = 1;
            } else {
                $input = 0;
            }
        } else {
            # Go back, display form to correct
            $input = 1;
        }
    }
    if ($input) {
        $query->param('step_input', 1);
    }
HTML views/form.html (Supposed to use HTML::Template)
Note that submit buttons should have two separate names. Some browsers like Firefox need this to distinguish. We can determine which button chosen by checking if field submit_confirm.x is existed.
It's tricky. Browser sends along a coordinate...
{% input family %}

         <tmpl_if name="step_input">
            <input type="image" src="confirm.gif" alt="確認">
        <tmpl_else>
            <input name="submit_edit" value="edit" type="image" src="edit.gif" alt="戻る">
            <input name="submit_confirm" value="confirmed" type="image" src="complete.gif" alt="登録する">
        </tmpl_if>
A little trick to writing view for both, by customised filter for HTML::Template
Having this, new shiny sugar syntax {% input family %} will render the input box, as well as validation message if found $message_family
sub custom_filter {
    my $text_ref = shift;
    
    # Define a new syntax {% input family %}
    $$text_ref =~ s/\{%\s*input\s+(.*?)\s*\%}
        /<tmpl_if name="step_input">
            <tmpl_if name="message_$1">
                <span class="message">
                    <tmpl_var escape=html name=message_$1>
                <\/span>
            <\/tmpl_if>
            <input 
        <tmpl_else>
            <tmpl_var escape=html name=$1>
            <input type="hidden"
        <\/tmpl_if>
        name="$1"
        value="<tmpl_var escape=html name=$1>">
        /gx;
}
Then register it:
    my $template = HTML::Template->new(
        filename => 'views/form.html',
        associate => $query,
        filter => \&custom_filter,
    );

No comments:

Post a Comment

New comment