Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

How to get unselected radio_group() items after submitting form

by slugger415 (Monk)
on Mar 08, 2011 at 15:35 UTC ( [id://892031]=perlquestion: print w/replies, xml ) Need Help??

slugger415 has asked for the wisdom of the Perl Monks concerning the following question:

Hi esteemed monks, I'm using CGI.pm to create a form with a series of radio_group() items. The choices are c, r, t and s; I have the default set to "-" so that none of them is selected until a user makes a selection.
foreach my $f (@files){ $query->radio_group(-name=>$f, -values=>['c','r','t','s'], -default=>'-'); } print $query->submit(-name=>'submit',-value=>'save');
This works fine when the form is first called; but once the user makes a few selections and clicks the submit button, all of the items where the user hadn't yet made a selection default to the first choice (c). Is there any way to prevent this from happening on subsequent submits? thank you, Scott

Replies are listed 'Best First'.
Re: How to get unselected radio_group() items after submitting form
by wind (Priest) on Mar 08, 2011 at 17:46 UTC

    The most likely culprit if your problem is the end_form function as demonstrated below.

    I created the following cgi script to test your issue

    #!/usr/bin/perl -wT use CGI; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); use strict; use warnings; my $q = CGI->new; print $q->header(); print <<"END_HTML"; <html> <body> <form method="post"> END_HTML foreach my $f (qw(foo bar baz)) { print "<p>$f</p>\n"; print $q->radio_group( -name => $f, -values => [qw(c r t s)], -default => '-', ) . "\n"; } print $q->submit(-name => 'submit', -value => 'save') . "\n"; print <<"END_HTML"; </form> </body> </html> END_HTML 1; __END__

    This appears to work as you desire. You can hit submit multiple times, and it will only autofill the radio buttons that were previously selected by the user.

    However, if I replace my hardcoded form tags with the cgi functions start_form and end_form, then your problem appears.

    #!/usr/bin/perl -wT use CGI; use CGI::Carp qw(fatalsToBrowser warningsToBrowser); use strict; use warnings; my $q = CGI->new; print $q->header(); print <<"END_HTML"; <html> <body> END_HTML print $q->start_form() . "\n"; # <------ Changed code foreach my $f (qw(foo bar baz)) { print "<p>$f</p>\n"; print $q->radio_group( -name => $f, -values => [qw(c r t s)], -default => '-', ) . "\n"; } print $q->submit(-name => 'submit', -value => 'save') . "\n"; print $q->end_form() . "\n"; # <------ Changed code print <<"END_HTML"; </body> </html> END_HTML 1; __END__

    I therefore suggest that you start your investigation there. At the very least you can hardcode your form tags and avoid the problem, but it appears the end_form function adds the following text that for some reason creates your issue.

    <div><input type="hidden" name=".cgifields" value="bar" /><input type +="hidden" name=".cgifields" value="baz" /><input type="hidden" name=".cgifields +" value="f oo" /></div>
    - Miller
      Interesting! Yes, Miller, that worked, much as I hate hard coding... :-)

      Thanks also to Wallisds for a more official solution.

      Scott

        If you look at the source code of CGI, you can discover the code inside end_form that is adding all the extra hidden variables.

        sub end_form { my($self,@p) = self_or_default(@_); if ( $NOSTICKY ) { return wantarray ? ("</form>") : "\n</form>"; } else { if (my @fields = $self->get_fields) { return wantarray ? ("<div>",@fields,"</div>","</form>") : "<div>".(join '',@fields)."</div>\n</fo +rm>"; } else { return "</form>"; } } }

        As you can see above, the $NOSTICKY global will prevent the extra hidden fields that lead to the undesired default values. After reading the documentation of $NOSTICKY, you can set this in two different ways. One of them is more global:

        use CGI qw(-nosticky);

        Or you can is isolate the change to just the end_form function by doing the following:

        print do {local $CGI::NOSTICKY = 1; $q->end_form()} . "\n";

        Or you can just simplify the whole process for yourself by writing a simple </form> tag. Really don't know why someone wouldn't just do that anyway as the CGI module really does try to do too much in my opinion.

        - Miller
Re: How to get unselected radio_group() items after submitting form
by wallisds (Beadle) on Mar 08, 2011 at 16:18 UTC

    You could add a Default button that would restore your radio group to default values when clicked.

    print $query->defaults('Restore to Default');
      Hm, not quite what I was looking for -- that removes the saved selections as well. To clarify, here's my initial view:
      label 1: ( )c ( )r ( )t ( )s label 2: ( )c ( )r ( )t ( )s label 3: ( )c ( )r ( )t ( )s label 4: ( )c ( )r ( )t ( )s label 5: ( )c ( )r ( )t ( )s
      A user makes selections on the first three:
      label 1: (x)c ( )r ( )t ( )s label 2: ( )c (x)r ( )t ( )s label 3: ( )c (x)r ( )t ( )s label 4: ( )c ( )r ( )t ( )s label 5: ( )c ( )r ( )t ( )s
      They click submit, and this appears:
      label 1: (x)c ( )r ( )t ( )s label 2: ( )c (x)r ( )t ( )s label 3: ( )c (x)r ( )t ( )s label 4: (x)c ( )r ( )t ( )s label 5: (x)c ( )r ( )t ( )s

      Note that 4 and 5 now have c selected.

      If I use print $query->defaults('Restore to Default');, it removes all selections from all rows.

      What I want it is to look like view #2 above, after clicking submit:

      label 1: (x)c ( )r ( )t ( )s label 2: ( )c (x)r ( )t ( )s label 3: ( )c (x)r ( )t ( )s label 4: ( )c ( )r ( )t ( )s label 5: ( )c ( )r ( )t ( )s
      thanks, Scott

        Ah. Thanks for the sample. Also, thanks to Wind for narrowing the issue to the start_form/end_form because I was not able to replicate the problem before using <form>.

        Anyway, here is my new solution:
        I updated file name to $f to match original sample.

        if ($which_radio_button eq q{}) { $query->delete("$f"); }

        see sample:

        #!/usr/bin/perl -w use CGI; use strict; my $query = CGI->new; print $query->header; my $button = $query->param('submit'); my @fs = ('test1.txt', 'test2.txt', 'test3.txt', 'test4.txt'); if ($button eq "save") { foreach my $f (@fs) { my $which_radio_button = $query->param("$f"); print "for $f you selected $which_radio_button<BR>\n"; if ($which_radio_button eq q{}) { $query->delete($f); } } #$query->delete_all(); } print "<html><body>"; print $query->start_form(); #print $query->defaults('Restore to Defaults'); foreach my $f (@fs) { print $query->radio_group(-name=>$f, -value=>['c','r','t','s'], -default=>'-'); print "<BR>"; } print $query->defaults('Return to default'); print $query->submit(-name=>'submit',-value=>'save'); print $query->end_form(); print "</body></html>";

        If you add $query->delete($f); where $f is empty you will achieve your desired result, as shown in the above example.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://892031]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2024-03-19 08:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found