Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re: CGI.pm Disillusionment

by perrin (Chancellor)
on Jun 05, 2003 at 00:35 UTC ( [id://263203]=note: print w/replies, xml ) Need Help??


in reply to CGI.pm Disillusionment

I think you'll find that the only thing about the HTML generation that most people like is the sticky widgets. You can easilly just use those and HEREDOC or template the rest. A much better solution in my eyes.

Replies are listed 'Best First'.
Re: Re: CGI.pm Disillusionment
by Cody Pendant (Prior) on Jun 05, 2003 at 00:46 UTC
    >I think you'll find that the only thing about the HTML generation that most people like is the sticky widgets.

    Well exactly. That's what I wanted. Forms which can report an error/missing field then pump out the field contents which are OK.

    Is there another solution for this kind of thing? It's easy enough to do field contents but checkboxes, radiobuttons and select lists always require some kludge. if(<param exists that matches the name>){print "selected" } or whatever

    Kludges are what I do best, but I'm trying to get away from that...
    --

    “Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.”
    M-J D

      Check out HTML::FillInForm for populating form fields without needing to use CGI.pm to generate the HTML. I use it very successfully with CGI::Application, HTML::Template and Data::FormValidator. A typical C::A runmode for me looks like the following:

      sub edit_form { my $self = shift; my $q = $self->query(); # load the HTML::Template object my $template = $self->load_tmpl('FormTemplate.tmpl') || die "Can't find template FormTemplate.tmpl"; if ($q->param('first_name')) { # The user has filled in the form, so we # check the values and update the database # if everything is OK my %form_data = $q->Vars; my %form_profile = ( required => [qw(first_name last_name)], optional => [qw(email)], constraints => { email => 'email', }, filters => [ 'trim' ], ); my ($valid, $missing, $invalid, $unknown) = Data::FormValidator->v +alidate(\%form_data, \%form_profile); if (@$missing || @$invalid) { # There were problems with the form my @errors; push @errors, map { { 'missing_'.$_ => 1 } } @$missing; push @errors, map { { 'invalid_'.$_ => 1 } } @$invalid; $template->param(errors => \@errors); } else { # Everything looks good, so update the database eval { ### Do some database stuff here My::DB::User->create($valid); }; if ($@) { $template->param(errors => [ { failed_on_update => 1} ]); } else { # The database was updated successfully # so display a success page $template->param(database_updated => 1); } } } return $self->fillinform(\$template->output()); } sub fillinform { my $self = shift; my $html = shift; # ref to string of HTML my $fif = new HTML::FillInForm; return $fif->fill(scalarref => $html, fobject => $self->query); }

      And the template would have the following fields in it:

      <TMPL_INCLUDE NAME="../header.tmpl"> <h2>Registration Form</h2> <TMPL_IF errors> <h4 class="error_hdr">There was a problem processing your request</h4> <ul> <TMPL_LOOP errors> <li class="error"> <TMPL_IF invalid_email>The email address you entered does not look l +ike a valid email address</TMPL_IF> <TMPL_IF missing_firstname>You are required to provide your first na +me</TMPL_IF> <TMPL_IF missing_lastname>You are required to provide your last name +</TMPL_IF> <TMPL_IF failed_on_create>Error: Failed to create the new user in t +he database.</TMPL_IF> </li> </TMPL_LOOP> </ul> </TMPL_IF> First Name: <input type="text" name="first_name" size="32" maxlength=" +72"><br /> Last Name: <input type="text" name="last_name" size="32" maxlength=" +72"><br /> email: <input type="text" name="email" size="32" maxlength=" +255"><br /> <input type="submit" name="submit" value="Submit"><input type="reset" + name="reset" value="Reset"><br /> <TMPL_INCLUDE NAME="../footer.tmpl">

      CGI::Application keeps my code structured nicely, HTML::Template allows me to separate design from code (including the content of error messages intended for the end-user), Data::FormValidator does most of the input field checking, and HTML::FillInForm gives me sticky form fields. And I usually top it off with Class::DBI for the database interface.

      This turned out to be a bit longer than I intended, but hopefully someone finds it useful (or someone points out where I can improve things :).

      Cheers

        That looks very interesting, cees, a good way around the stickiness issues. Thanks for posting the code.
        --
        “Every bit of code is either naturally related to the problem at hand, or else it's an accidental side effect of the fact that you happened to solve the problem using a digital computer.”
        M-J D

      Well, I dunno about it's kludge-worthiness, but for checkboxes, radio buttons, and selects for a quick form I had to do recently I went with extra template tags in the respective tags then in my script I set the appropriate values to 'selected' or 'checked' so my template looks like:

      <p>[% error.message %]</p> <input type="checkbox" name="field1" value="1"[% checked.field1 %]> <select name="field2"> <option value="val1"[% selected.val1 %]>Value 1</option> <option value="val2"[% selected.val2 %]>Value 2</option> </select> <input type="radio" name="field3" value="a"[% checked.field3_a %]> <input type="radio" name="field3" value="b"[% checked.field3_b %]> <input type="radio" name="field4" value="a"[% checked.field4_a %]> <input type="radio" name="field4" value="b"[% checked.field4_b %]>

      And after processing:

      <p>Please select a value for Field 4</p> <input type="checkbox" name="field1" value="1" checked> <select name="field2"> <option value="val1">Value 1</option> <option value="val2" selected>Value 2</option> </select> <input type="radio" name="field3" value="a" checked> <input type="radio" name="field3" value="b"> <input type="radio" name="field4" value="a"> <input type="radio" name="field4" value="b">

      Of course you're still going to have to process the input and set the appropriate values, but for that I created a config type hash containing the names of the different inputs grouped by type. For each I also specified a human readable label. Then I created a 'required' hash of input fields.

      The script then checks that any fields in the 'required' hash have been specified and if not, uses their labels to create the error message.

      Then we go through the field hashes to set appropriate values for 'selected' and 'checked'.

      cheers,

      J

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-03-29 06:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found