[lug] perl and cgi.pm

Michael J. Hammel mjhammel at graphics-muse.org
Fri Feb 8 07:52:18 MST 2002


Thus spoke Tkil
> A checkbox group is a set of HTML checkboxes, all with the same name,
> but different values, and [typically] diffrent checked/unchecked
> states.
> 
> The easiest way to do it is to specify all these at once:
> 
>   my @cb = $q->checkbox_group( -name => 'my_group',
>                                -values => [ qw( foo bar baz quux ) ],
>                                -default => [ qw( foo baz ) ] ) );

This is the easiest way, but not if the values to be used are coming from a
database and you're getting those by iterating through the results of an SQL
SELECT statement.

> Each element of the array is a simple string containing the HTML
> representing each checkbox; you can manipulate this anyway you like.
> One thing I've done with it is to split a list into two columns:
> 
>   my $left_cb  = join '<br />', @cb[ 0 .. $#cb/2 ];
>   my $right_cb = join '<br />', @cb[ $#cb/2+1 .. $#cb ];
> 
>   print $q->Tr( $q->td( { -valign => 'top' }, [ $left_cb, $right_cb ] ) );

That's cool.  I didn't know you could do this with arrays.  My perl, eeze not
sooo good.

> I think I answered this above -- they're strings.  As for how to find
> that out, may I suggest debugging prints?
> 
> | $ perl -MCGI=:standard -lwe \
> |     'print join "\n", checkbox_group( -name => "my_group",
> |                                       -values => [ qw( foo bar baz quux ) ], 
> |                                       -default => [ qw( foo baz ) ] );' \
> |     < /dev/null
> | > > > > (offline mode: enter name=value pairs on standard input)
> | 
> | <INPUT TYPE="checkbox" NAME="my_group" VALUE="foo" CHECKED>foo
> | <INPUT TYPE="checkbox" NAME="my_group" VALUE="bar">bar
> | <INPUT TYPE="checkbox" NAME="my_group" VALUE="baz" CHECKED>baz
> | <INPUT TYPE="checkbox" NAME="my_group" VALUE="quux">quux

Cool.  More new info.  :-)

> You have to be careful with the terminology here.  Do you really want
> to change the *value* of the checkbox within a group, or just modify
> its checked / unchecked state?  Either way, you could muck about with

I want to actually change the value.  For example, each checkbox is a cancel
button for an order, so the value is the record id for that order.  My
problem is that I don't have those record ids in one lump to pass to
checkbox_group().

> the strings using regex replacements -- but that feels fragile to me.
> Better to just create them with the correct values in the first place.

I could do this by changing the flow of my script - grab all the data from
the db at once and then shove it into the checkboxes - but I don't like that
flow.  I prefer doing the necessary steps on each iteration because it makes
it easier for me to see what I was doing when I have to go back months later
and revisit the code (this code actually started life as part of the CLIQ
registration system, which I wrote over 2 years ago).

> I typically create all the boxes up front, then pick them off as I
> need them.  Or, if it is reasonable to do so, I can also choose to use
> a more list-processing / functional programming style, modifying the
> list as I go.  This works particularly well with CGI's Tr and td
> methods, which do some magic mapping when appropriate:
> 
>   my $table = $q->table( $q->Tr( [ map $q->td($_), 
>                                        $q->checkbox_group( ... ) ] ) );

I'm old.  Magic scares me.  I prefer procedural, top down cruft where I can
see all the mechanics of what I'm trying to accomplish.  I'm with Mulder:
trust no one.  If I have time I'll have to explore what this little bit of
code does.  For now, I just embed td's inside Tr's as function alls and pass
appropriate args, pushing the results into an array.

> Using the same arguments to checkbox_group as above, this code yields
> something like this:
> 
> | $ perl -MCGI=:standard -lwe \
> |     '@cb = checkbox_group( -name => "my_group",
> |                            -values => [ qw( foo bar baz quux ) ], 
> |                            -default => [ qw( foo baz ) ] ); 
> |      $_ = table( Tr( [ map td($_), @cb ] ) );
> |      s+</tr>+$&\n+ig;
> |      print;' < /dev/null
> | > > > > > > 
> | <TABLE>
> |  <TR><TD><INPUT TYPE="checkbox" NAME="my_group" VALUE="foo" CHECKED>foo</TD></TR>
> |  <TR><TD><INPUT TYPE="checkbox" NAME="my_group" VALUE="bar">bar</TD></TR>
> |  <TR><TD><INPUT TYPE="checkbox" NAME="my_group" VALUE="baz" CHECKED>baz</TD></TR>
> |  <TR><TD><INPUT TYPE="checkbox" NAME="my_group" VALUE="quux">quux</TD></TR>
> | </TABLE>


Ahhh.  I see how this works now.  This would be useful, as long as you know
ahead of time what your values are.  In my case, I didn't have that since I
was doing all of this by iterating though the SELECT.  

> Does this answer your questions?

Yes and no.  I do see how you're doing this, but it didn't fit my needs.  As
it turned out, I just just shoved ordinary HTML strings in for the checkboxes
where I needed them instead of relying on CGI.pm to do it for me.  It works.
I even read some online tutorials for CGI.pm which suggested that there were
cases where such hard coded HTML was preferrable. So I guess it's a
reasonable solution.

Thanks for taking the time to explain this though.  It certainly expands my
Perl knowledge.  :-)

-- 
Michael J. Hammel           |
The Graphics Muse           |       I refuse to star in your psychodrama.
mjhammel at graphics-muse.org  |
http://www.graphics-muse.com 



More information about the LUG mailing list