Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Sticky Forms

by JsnHendry (Novice)
on Apr 16, 2007 at 09:09 UTC ( #610294=perlquestion: print w/replies, xml ) Need Help??

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

I am completely new to Perl. I am having trouble trying to create a "sticky" form. I have created the form using CGI.pm, with another cgi script validating the entries. The validation script also has a link taking the user back to the form page. Whenever this link is used, the field entries on the form are missing, i.e. the form is not sticky. Can anyone please help me to solve this problem. I have read that cgi.pm makes forms sticky automatically, but I'm not sure whether this is true. I am also having trouble finding a basic tutorial or example code to help. Any advice would be gratefully received.

Replies are listed 'Best First'.
Re: Sticky Forms
by f00li5h (Chaplain) on Apr 16, 2007 at 09:36 UTC

    You may want to have a look at CGI::FormBuilder. It's forms are sticky, and have both serverside and javascript validation.

    It's neat.

    Update I think that CGI.pm only makes forms "sticky" in as much as they preserve their values each time the form is submitted (ie CGI.pm automatically adds the value="stuff-from-form" when you use it's input method.

    Even with this kind of stickyness, a link back to foo.cgi won't post the data to the form that foo.cgi generates, if you want to preserve data like that on the server side, you can look at CGI::Session, which will allow you to associate the contents of the form with an HTTP cookie sent to the browser.

    @_=qw; ask f00li5h to appear and remain for a moment of pretend better than a lifetime;;s;;@_[map hex,split'',B204316D8C2A4516DE];;y/05/os/&print;
      Although it won't by itself solve your problem, I will second the mention of CGI::FormBuilder. It does lots of very cool things and the documentation is quite good.
Re: Sticky Forms
by reasonablekeith (Deacon) on Apr 16, 2007 at 09:33 UTC
    You just need to save the value and restore it to your input fields someway.

    Where you're actually keeping the data (server-side data against a session, posted form paramters etc... ) would determine the method. Here's a simple example with posted data. Firstname is sticky after the form is submitted, surname isn't.

    #!/usr/bin/perl use CGI; use CGI::Carp qw(fatalsToBrowser); use warnings; use strict; my $q = new CGI; my $firstname = $q->param('firstname'); print qq|content-type: text/html\n\n|; print qq|<form action="$ENV{SCRIPT_NAME}" method="post" name=f>\n|; print qq|<input name="firstname" type="text" value="$firstname"/><hr/> +|; print qq|<input name="surname" type="text"/><hr/>|; print qq|<input type="submit" name="form_submit" value="go">|;
    ---
    my name's not Keith, and I'm not reasonable.
Re: Sticky Forms
by GrandFather (Saint) on Apr 16, 2007 at 09:45 UTC

    The Tutorials section has a CGI Programming section that you may find of help. I presume you have already found the CGI documentation? Not much mention of stickiness in there though.

    It may be that Populating forms is of some help. If you continue to have trouble post a small sample script demonstrating the problem.


    DWIM is Perl's answer to Gödel
Re: Sticky Forms
by ChemBoy (Priest) on Apr 16, 2007 at 16:12 UTC

    It is true that CGI has sticky form elements by default. Your problem is that nobody has explained exactly what is meant, in this situation, by "sticky form elements." So let me give it a shot.

    At a basic level, CGI.pm's stickiness consists of exactly this: when you submit a form, via GET or POST, to a script that uses the functions (or methods) defined in the module CGI both to parse its input and to generate a new form in its output, then form elements in the output that have the same name as form elements that were parsed as part of the input will, unless otherwise specified (usually using the -value and -force arguments to the code-generating method or subroutine), be pre-populated with the values that they had in the incoming GET or POST request.

    Clear as mud? Was afraid of that...

    To put it in more relevant terms for you: for your form to be pre-populated with the values from a previous invocation, the script has to get those values from the browser when it's called. So your strategy of having a separate script to validate, with a simple hard-coded link back to the original script for corrections, cannot possibly work. However, you have various options that can work, with greater or lesser amounts of work on your part:

    1. Combine your validation and correction scripts. That is, instead of having one script issue the form and another validate its inputs, have one script that does both. Then, instead of a link back to the original form, you simply print some explanatory message ("Your input was missing values Y, Z, and X"), and print the form again. This will get you your sticky values automatically (assuming you're using CGI to print out your form elements, of course).
    2. Change the link back from the validation page to the input page from a hard-coded one to a dynamic one that includes the parameters you wish to have your input page pre-populated with. There are a couple of ways to do this, using the URI module or the messing around with the self_url method of your CGI object, none of which I really like very much or use often enough to be able to write an example off the cuff. Sorry.
    3. You can create a form on the validation page that does roughly the same job, only making the browser and CGI do all the work for you. Then instead of a link back, you'll have a submit button. This one I am willing to illustrate (though I don't necessarily endorse it):
      my $hidden_form = $cgi->start_form( -name=>"resubmission, -method=>"POST", -action=>$input_cgi_location, ); foreach my $p ($cgi->param) { $hidden_form .= $cgi->hidden($p); } $hidden_form .= $cgi->submit( -name=>"resubmitted", -value=>"Return to input form", ); $hidden_form .= $cgi->end_form;
      (Please note that the above is not in any way tested.)

    I hope some of that was helpful—good luck!



    If God had meant us to fly, he would *never* have given us the railroads.
        --Michael Flanders

Re: Sticky Forms
by jdrago_999 (Hermit) on Apr 16, 2007 at 15:25 UTC
    Remember to keep your forms cross-site-scripting safe.

    Example:
    #!/usr/bin/perl -w use strict; use CGI (); my $q = CGI->new(); # Your logic here. print <<EOF; <html><body> <form name="form1" action="form.pl" method="POST"> EOF print q~ Username: <input type="text" name="user_name" value="@{[ HTMLEncode( $q->param('user_name') ) ]}" > <br> Password: <input type="text" name="user_password" value="@{[ HTMLEncode( $q->param('user_password') ) ]}" > <br> <input type="submit" value="Submit"> ~; print <<EOF; </form> </body> </html> EOF #========================================================== sub HTMLEncode { my ($str) = @_; $str =~ s/&/&amp;/g; $str =~ s/"/&quot;/g; $str =~ s/</&lt;/g; $str =~ s/>/&gt;/g; return $str; }# end HTMLEncode()
Re: Sticky Forms
by Rhandom (Curate) on Apr 16, 2007 at 16:18 UTC
    Wow. I am baffled by how many of the above examples actually embed the html in the CGI and try and interpolate the values directly into the html. This is only marginally less offensive as interpolating variables into SQL (not using placeholders).

    Use either CGI::Ex::Fill or HTML::FillInForm to get your values into the form.

    I'll leave it to you whether you generate your form dynamically, or if you use a static generated form, or a hybrid dynamic/static form created using a template system (you are using a templating system right?). The fill methods allow for generating the form however and then getting the values into the right places.

    use CGI; use CGI::Ex::Fill qw(fill); my $q = CGI->new; my %default = ( foo => 'FooFoo', bar => 'BarBar', baz => 'BazBaz', ); foreach my $k (keys %default) { $q->param($k, $default{$k}) if ! defined $q->param($k); } my $html = ' <form> <input type="text" name="foo"> <textarea name="bar"></textarea> <select name="baz"> <option>Bing</option> <option>BazBaz</option> <option>Bang</option> </form> '; fill({text => \$html, form => $q}); print $html;
    Which would print the following:
    <form> <input type="text" name="foo" value="FooFoo"> <textarea name="bar">BarBar</textarea> <select name="baz"> <option>Bing</option> <option selected="selected">BazBaz</option> <option>Bang</option> </form>


    my @a=qw(random brilliant braindead); print $a[rand(@a)];

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2022-10-03 17:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My preferred way to holiday/vacation is:











    Results (15 votes). Check out past polls.

    Notices?