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

I am assuming that before hitting the submit button I can not use Perl to validate entries as they are entered on an HTML Form. I am assuming that Javascript is the only option I have available.

I already plan to validate the data after the submit via Perl and then enter the data into the database but I am trying to build a web form that is somewhat dynamic and validates on the fly.

Another problem I am having is that I have a section of the form which is more of a table. Sometimes the table is 1 record wide and others it is up to 10 records wide. There are about 8 different fields I am looking at.

My current option is to build a multipart form. The first form would collect all the data I need not including the table. One of the entries in this form is to ask how many records are to be entered. After validating this sheet and posting the data to the database I then would go to another form setup with this table setup according to the number entered initial page.

I would like to be able to have an interactive page which would "throw" this table up with the correct number of records setup after entry of a new number in the assocated field.

If I understand the CGI, Perl and web stuff however perl can only setup the format of the page and the initial default data. Once sent to the browser there is no more interaction with the browser until the user hits the "submit" button. Thus in order to make an interactive web page I would have to use javascript.

Replies are listed 'Best First'.
Re: Can perl do interactive forms?
by jlongino (Parson) on Jan 01, 2002 at 06:27 UTC
    I would venture to say that in most situations, the JavaScript/Perl route is the best/easiest way to go. However, you shouldn't rely entirely on JavaScript to do your validation. Client-side validation can be useful in the sense that it is user friendly, but you must protect yourself on the server-side since it is possible to bypass your JavaScript checks and invoke your CGI using bogus (potentially harmful) data.

    There are all sorts of active scripting languages that could be used provided you meet all the necessary requirements (right platform, right web server software installed, etc.). E.G., PerlScript, VBScript and even CobolScript (as jcwren laments here).

    This node, CGI and JavaScript, should also prove interesting reading.

    HTH,

    --Jim

    Update: I see after I posted that you were planning to validate via Perl in any case. So pardon the rant on that count. :)

(cLive ;-) Re: Can perl do interactive forms?
by cLive ;-) (Prior) on Jan 01, 2002 at 06:38 UTC
    JavaScript's your best bet.

    Even if you want to auto check using Perl after each input, you'd still need to use something like onBlur (which is still JavaScript) to force the call to submit form (JS again).

    .02

    cLive ;-)

      Bad idea: submitting a form to the server using onBlur()!

      Use JavaScript for what IMHO it appears to have been intended: as glue for holding together a web page, not for simplifying CGI coding. In other words, as little as possible within a given context.

      If you're planning to do field validation at the browser (using JS), don't presume you no longer need it on the server (using Perl). What's to prevent some saavy hacker from viewing at your HTML/JS source and dummying up a URL using HTTP GET syntax? How does your (Perl) script react to unvalidated and/or clearly bad input?

      Use Javascript or don't use it. Just make sure your forms work (however crippled it makes the UI) with JS disabled.

      dmm

      You can give a man a fish and feed him for a day ...
      Or, you can
      teach him to fish and feed him for a lifetime
        I'm not suggesting you use it for form submission in the 'traditional' sense, only as a way of checking input server side on the fly.

        yes, technically the form is submitted 'onBlur', but is only 'processed' when the submit button is hit.

        If everything's OK at that point you can just return a 204 HTTP header.

        I agree, it would be a nightmare, hence my suggestion that JavaScript was the best bet. I also agree that it can't be relied on for input verification, but if you use it to verify input of a form and still verify through CGI, it would be the most efficient as far as the user experience was concerned. Here's an example of how it could work:

        #!/usr/bin/perl -w use strict; use CGI; use CGI::Carp 'fatalsToBrowser'; my $q =new CGI; # criteria for fields my %regexp = (username => '^\w+$', table_rows => '^\d{1}$', table_cols => '^\d{1}$' ); # check an input if ($q->param('check_field')) { my $input = $q->param('check_field'); check_input_ok($input); # ok, so do nothing print "Status: 204 OK\n\n"; exit(0); } # process form elsif ($q->param()) { process_form(); } # present else { show_form(); } sub check_input_ok { my $input_name = $_[0]; my $input_value = $q->param($input_name); # check input fits criteria - simple eg here if ($input_value =~ /$regexp{$input_name}/) { # input's OK # represent form if input was table_rows or table_cols, and both v +alid if ( $q->param('check_field') && $q->param('table_rows') && $q->param('table_cols') && ( ($input_name eq 'table_rows') || ($input_name eq 'table_col +s') ) ) { show_form(); } } else { # delete and re-present $q->delete($input_name); show_form("Input $input_name is invalid - please try again"); } } sub show_form { # display form # grab error, if any my $err_message = $_[0]; # reset check_field element $q->param('check_field',''); # here's the javascript my $js = <<'_END_'; function check_input(fieldname) { document.testform.check_field.value = fieldname; document.testform.submit(); } _END_ if ($err_message) { $err_message =~ s/'/\\'/; $js .= "alert('$err_message');\n"; } print $q->header(), $q->start_html(), $q->script({-language=>'JavaScript'},$js), $q->start_form(-name=>'testform'), $q->hidden('check_field'), 'Username: ', $q->textfield(-name=>'username','-onBlur',"check_input('userna +me')"), $q->br, 'Number of Rows(1-9): ', $q->textfield(-name => 'table_rows', -size => 2, -onBlur => "check_input('table_rows')" ), 'Number of Cols(1-9): ', $q->textfield(-name => 'table_cols', -size => 2, -onBlur => "check_input('table_cols')" ), $q->p(); # do we need to show a table? if ($q->param('table_rows') && $q->param('table_cols')) { # html to create table here... print $q->start_table({-border=>1}), $q->start_Tr, $q->th(); # header row for (1..$q->param('table_cols')) { print $q->th("C$_"); } print $q->end_Tr; # content for my $row (1..$q->param('table_rows')) { print $q->start_Tr, $q->th("R$row"); for (1..$q->param('table_cols')) { print $q->td("C$_ R$row"); } print $q->end_Tr; } print $q->end_table(); } # finish off form print $q->submit(-value=>'process', -onClick=>"document.testform.check_field.value = '' +;"), $q->end_form, $q->end_html; exit(0); } sub process_form { # check all fields again for (keys %regexp) { check_input_ok($_); } # everything submitted and checked, so continue print $q->header('text/plain'), 'process form here'; exit(0); } sub err { print $q->header('text/plain'), $_[0]; exit(0); }

        This is only rough code, but you get the general idea...

        cLive ;-)