http://qs1969.pair.com?node_id=400844

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

Greetings monks, as I wave the white flag of surrender

I am going in circles trying to build a cgi form inside TemplateToolkit. I want the form action to return to the same runmode, or anywhere else for action processing, but no matter what I do, it goes back to the first runmode/web page.

[% INCLUDE header.tt2 %] #this is page3.tt2 [% USE CGI %] [% CGI.start_form(Action =>'/webapp/index.pl?rm=page3') %] viewer: [% CGI.textfield({Name => 'view' Value =>params.view Size => 10 Max +length => 10}) %]<br/> phone: [% CGI.textfield({Name => 'phone'Value => params.phone Size => 10 M +axlength =>10}) %]<br/> [% CGI.submit({Name => 'cm' Value => 'login' Class => 'grid'}) %] </form> [% INCLUDE footer.tt2 %]
Most items I put in the action section cause an empty html page to be rendered. This example works, but takes me back to index.tt2 instead of sticking at page3.tt2.

Attempts to code a form in perl in the pm-module which accompanies this tt2 app have had similar results. I had a similar form in HTML::Mason and had no problem making it come back to the same form for digesting the results, but my searches about Template::Toolkit and cgi forms have turned up no useful info.

UPDATE:I realized I forgot to mention I am running this under CGI::Application (the runmode comments give this point away)

thanks in advance

--bibo

Replies are listed 'Best First'.
Re: TemplateToolkit and CGI Forms
by jeffa (Bishop) on Oct 20, 2004 at 15:46 UTC

    Just to illustrate what perin said, i ran your TT template through the tpage command line tool, cleaned up some extraneous tag attributes and used the output for a CGI test script. Feel free to run this on your own:

    use strict; use warnings; use Data::Dumper; use CGI::Pretty qw(:standard); print header; print while <DATA>; print pre( Dumper { CGI::Vars() } ); __DATA__ <form method="post" action="?rm=page3"> viewer: <input type="text" name="view" size="10" /><br/> phone: <input type="text" name="phone" size="10" /><br/> <input type="submit" name="cm" value="login" /> </form>
    Or test it out here: http://unlocalhost.com/cgi-bin/post_get.cgi -- notice how your run mode parameter goes to a ... different place. Interestingly enough, i really thought that switch from POST to GET would solve the problem, but it does not. You have to pass a hidden param.

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: TemplateToolkit and CGI Forms
by gellyfish (Monsignor) on Oct 20, 2004 at 13:05 UTC

    It appears that output from this template is largely correct (though I am totally confused as to why you are using the CGI HTML generation methods in the template when it would be simpler and clearer just to type the form in), I would guess that the problem lies in the way that index.pl is dealing with the rm parameter rather than anything to do with the form itself.

    /J\

Re: TemplateToolkit and CGI Forms
by perrin (Chancellor) on Oct 20, 2004 at 15:03 UTC
    Putting a query string into your form action is not a good idea. Instead, make a hidden form input called rm with the value page3.

      Ah yes, I didn't spot this (the request method) before - more specifically when you are using CGI.pm with a POST request method any query parameters supplied as part of the URL will be ignored by design (although you can uncomment part of the code for this not to happen.) So yes, when you are using a POST method you should be using a hidden field rather then putting the parameter into the URL.

      /J\

Re: TemplateToolkit and CGI Forms
by Anneq (Vicar) on Oct 23, 2004 at 02:40 UTC

    Here is what I do to use one template form for submitting the form and for processing results. I use a default (or no) run mode for the initial form display. When the form is submitted, the form's action url changes the run mode to a specific one for handling the submitted form. I make use of a separate CGI parameter (e.g., page) to indicate the resource (template page) to be accessed. This way, I can reuse the same run mode names but for different situations, for example, add a record to different databases. The action run mode could be 'add_record', while the resource may be 'some_section.employee.add_record' or 'some_section.inventory.add_record'. There is a methods module for each database that handles the required database actions.

    A template component handling the form input and result might look like:

    [% IF msg == 'success' %] <p>You were successful.</p> [% ELSE %] [% msg IF msg %] ... show the form because something went wrong ... [% END %]

    The CGI::Application run modes would look like:

    $self->run_modes( 'default' => 'default',\ 'create_database' => 'database_action', 'add_record' => 'database_action', 'delete_records' => 'database_action', 'modify_record' => 'database_action', 'other_run_mode' => 'other_sub', );

    In my CGI::Application module, here is the run mode sub:

    sub database_action { my $self = shift; my $q = $self->query(); my $me = "$self->database_action()"; # Used in result messages for + debugging my @page = split('\.', $q->param('page')); # Resource requested, f +or example, page='section.inventory.add_record' my $database_name = $page[$#page - 1]; # The second-last page elem +ent is the database my $database_action = $page[$#page]; # The resource as well as the + method # Do some things here relating to the run mode my $pkg = "My::SomePath::$database_name"; eval "require $pkg;"; if ($@) { $result = "<p>$me: Failed to require $pkg.</p> <p>\$\@ says: $@ and <br/>\$! says: $! and<br/>\$result: $resu +lt</p>"; } my $method_call = "$pkg->${database_action}(\$self)"; $result .= eval "$method_call;"; if ($@) { $result .= "<p>$me: $method_call failed.</p> <p>\$\@ says: $@ and <br/>\$! says: $! and<br/>\$result is: $resul +t</p>"; } my $output .= My::CGIOut->build_page($self, $result); # Process th +e template return $output; }

    And in a module (My::SomePath::SomeDB) to handle reusable code used by the run mode:

    sub do_some_database_action { my $self = shift; my $cgi_app = shift; my $q = $cgi_app -> query(); my $session = $cgi_app->param('session'); my $result = ''; my $me = "$self->do_some_some_database_action()"; # Used in result + messages for debugging #----------------------------------------------------------------- +---------- # Do Something with query parameters like Data::FormValidator #----------------------------------------------------------------- +---------- my $result = My::OtherModule->validate_something($cgi_app); return $result if ($result); #----------------------------------------------------------------- +---------- # Do Something if successful #----------------------------------------------------------------- +---------- #----------------------------------------------------------------- +---------- # Finish up #----------------------------------------------------------------- +---------- $result = 'success' if (!$result); return $result; }

    Anne