Retrieving Form Input

Thus far, we have used CGI.pm's param() method for retrieving form values. This works fine until you have to retrieve the form valuess from a repeating form fragment.

The form values can be retrieved via the ZForm->values() method. This returns a reference to a hash of the form values. The form fragment value will be a reference to an array of hashes, one hash for each occurrence of the form. Let's check out yet another clever example based on poc.cgi:

#!/usr/bin/perl

use lib '.';
use strict;
use warnings;
use CGI;
use CGI::Carp;
use POC;

# Create a new cgi object
my $q = new CGI;

# Create an instance of our form and attach the cgi object
my $f = new POC(cgi => $q);

# Placeholder for output
my $output = '';

# Define some default values
my $default_vals = {
    'rm'    => 'validate',
    'fname' => 'Coach',
    'lname' => 'Z',
    'phone' => [
                {'number' => '555-5551',
                 'type' => '0'},
                {'number' => '555-5552',
                 'type' => '3'},
                {'number' => '555-5553',
                 'type' => '2'},
                {'number' => '555-5554',
                 'type' => '1'},
                ]
            };


if(defined($q->param('rm')) && $q->param('rm') eq 'validate') {
    # User clicked submit, so validate the form
    if($f->validate()) {
        # It validated! Display the data
        $output = data_tree($f->values());
    } else {
        # Didn't validate, so display the form with errors
        $output = $f->display();
    }
} else {
    # The user has not yet clicked submit, so display the empty form
    $f->values($default_vals);
    $output = $f->display();
}

# Display the output
print($q->header, $output);

# Walk the data tree
sub data_tree {
    my $values = shift();
    my $output = '';
    my $v;
    my $array_ref;

    # Iterate over each entry in the hash table
    foreach(keys(%$values)) {
        # In this example, if the reference is an array, 
        # then the values belong to a form fragment. In real life,
        # an array could signify a scrolling list. However, this
        # is just a contrived example, and we can play stupid.
        if(ref $values->{$_} eq 'ARRAY') {
            $array_ref = $values->{$_};
            foreach(@$array_ref) {
                # Recursion with a base case is your friend.
                $output .= data_tree($_);
            }
        } else {
            $output .= "$_: $values->{$_} </br>\n";
        }
    }

    return $output;
}