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;
| [reply] [d/l] [select] |
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.
| [reply] |
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.
| [reply] [d/l] |
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
| [reply] |
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:
- 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).
- 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.
- 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
| [reply] [d/l] [select] |
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/&/&/g;
$str =~ s/"/"/g;
$str =~ s/</</g;
$str =~ s/>/>/g;
return $str;
}# end HTMLEncode()
| [reply] [d/l] |
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)];
| [reply] [d/l] [select] |