Beefy Boxes and Bandwidth Generously Provided by pair Networks Joe
Pathologically Eclectic Rubbish Lister

Browser-viewable HTML::Template templates

by dws (Chancellor)
on Jan 11, 2003 at 22:59 UTC ( #226148=perlmeditation: print w/ replies, xml ) Need Help??

I while back I posed a question about handling checkboxes and radio buttons in HTML::Template templates. I was looking for a scheme that de-coupled page design from application development, so that both could proceed in parallel. In particular, I wanted to be able to view templates directly in a browser (to verify design changes), while also supporting the ability to generate a page with specific radio boxes and check boxes checked.

A first glance, there are three approaches to generating pages that have specific boxes checked.

One either has to produce the HTML input tags in code, via
$template->param(foo_input => "<input type=checkbox name='foo'" . $foo_checked ? " checked>" : + ">"); ... <TMPL_VAR foo_input>
or one has to temporarily break the HTML in the template by doing
$template->PARAM(foo_checked => $foo_checked); ... <input type=checkbox name="foo" <TMPL_IF foo_checked>checked</TMPL_I +F>>
or one has to bloat the template with conditional logic
$template->param(foo_checked => $foo_checked); ... <TMPL_IF foo_checked> <input type=checkbox name="foo" checked> </TMPL_ELSE> <input type=checkbox name="foo"> </TMPL_IF>
All of these approaches work, but none allow the unexpanded template to be viewed in a browser. In the first scheme you get an empty hole, the second scheme results in invalid HTML, and the third scheme shows each input control twice.

I didn't find a clean scheme, but did settle on a hybrid one that works.

When the initial page design is templatized,

<input type=checkbox name="foo">
gets turned into
<TMPL_IF false><input type=checkbox name="foo"></TMPL_IF><TMPL_VAR f +oo_input>
with   $template->param(false => 0);
When viewed in a browser, the original input tag is displayed. But when the template is expanded, the tag in the template gets discarded and a dynamically generated tag takes its place.

The downsides of this scheme are that HTML is being produced in code, and that template designers need to coordinate changes with the application developers (which is true anyway). But it works, and it also works when generating dynamic pop-up menus using select tags.

If anyone has a better approach, I would love to hear about it.

Comment on Browser-viewable HTML::Template templates
Select or Download Code
Re: Browser-viewable HTML::Template templates
by Aristotle (Chancellor) on Jan 12, 2003 at 02:43 UTC

    Yuck. If you have to synchronize the template with the code, why use a template at all?

    If you ask me, the best solution is to switch to Template Toolkit 2 and do something like this:

    [% IF foo_checked ; '<input type=checkbox name="foo" checked>' ; ELSE +-%] <input type=checkbox name="foo">[% END %]
    And you can also change the tag delimiters so that you can make it look f.ex like so:
    <!--// IF foo_checked ; '<input type=checkbox name="foo" checked>' ; E +LSE --> <input type=checkbox name="foo"><!--// END -->
    That way the browser sees valid HTML and the template can still generate either variant. HTML::Template ain't bad, but its syntax is really too restrictive IMHO.

    Makeshifts last the longest.

Re: Browser-viewable HTML::Template templates
by cLive ;-) (Parson) on Jan 12, 2003 at 08:50 UTC
    Why not write a quick CGI script to display a template?
    #!/usr/bin/perl use strict; use warnings; use CGI; use CGI::Carp 'fatalsToBrowser'; my $template_dir = '/path/to/template_dir'; my $q=CGI->new(); if ( $q->param() ) { show_template(); } else { show_form(); } sub show_template { my $template = $q->param('template'); open(TMPL,"$template_dir/$template") || die $!; my $content = join '',(<TMPL>); close(TMPL); $content =~ s/<TMPL[^>]*>//gs; print $q->header(), $content; exit(0); } sub show_form { print $q->header, $q->start_html, $q->start_form, 'Template: ', $q->textfield('template'), $q->submit, $q->end_form, $q->end_html; exit(0); }

    That way, you can set up a checkbox like this:

    <input type="checkbox" name="foo" <TMP_VAR NAME=FOOCHECKED>>

    where FOOCHECKED is either '' or 'checked'

    Note - obviously I assume here you know how to taint check if this is on a live server (or to use an IP check to limit access etc) - this is just a rough outline.


    cLive ;-)

      Good suggestion. I think it's easier not to duplicate HTML::Template's parsing if you already have it on hand though:
      sub show_template { my $t_file = $q->param('template'); require HTML::Template; my $t = HTML::Template->new_file($t_file); # and don't fill in any values print $q->header(), $t->output; exit(0); }

      Makeshifts last the longest.

      Why not write a quick CGI script to display a template?

      This is as much a human issue as it is a technical one.

      The designers I'm dealing with are not developers. Setting things up so that they can open a template directly in a browser is easy for them. Easy in this case is Good. Requiring that they copy the template onto a web server, then pull up a form and name the template, adds nuisance work to their plates. Nuisance in this case is Bad.

      If I was working with development-savvy page designers, a CGI to pre-process the template mght be an option.

Re: Browser-viewable HTML::Template templates
by Anonymous Monk on Jan 12, 2003 at 16:41 UTC
    I always create harness code at the same time I create my HTML::Template files. This has the benefit of giving your designer a realistic platform on which to do their work. Implementing design on a faked-up template, as the TT user suggested above, only opens up the door to creating a broken interface.

    Writing harness code at the same time you create your template files also has the added benefit of forcing me to think through the application and template functionality. Once I have a solid understanding of the functionality, it is a breeze to write a simple skeletal framework.

    For creating web applications I use CGI::Application. Using this module, realistic harness code is easily created through the mechanism of run-modes. The more realistic the code is from the beginning, the more bug-free the final product will be. To illustrate what I'm talking about, here's an example of what a test harness for application and template development might look like:

    package My::WebApp; use base qw/CGI::Application/; sub setup { my $self = shift; $self->start_mode('show_form'); $self->run_modes( show_form => 'show_form', list_results => 'list_results', show_detail => 'show_detail', ); } sub show_form { my $self = shift; my $tmpl = $self->load_tmpl('search_form.tmpl'); # Set up example data for template $tmpl->param('foo_checked' => '1'); return $tmpl->output(); } sub list_results { my $self = shift; my $tmpl = $self->load_tmpl('list.tmpl'); # Set up example data for template $tmpl->param('widget_loop' => [ { widget_name => 'widget_one', widget_id => '1' }, { widget_name => 'widget_two', widget_id => '2' }, { widget_name => 'widget_three', widget_id => '3' }, ]); return $tmpl->output(); } sub show_detail { my $self = shift; my $tmpl = $self->load_tmpl('detail_view.tmpl'); # Set up example data for template $tmpl->param('foo_id' => '1'); $tmpl->param('foo_name' => 'widget_one'); $tmpl->param('foo_checked' => 1); return $tmpl->output(); }
Re: Browser-viewable HTML::Template templates
by Anonymous Monk on Jan 14, 2003 at 23:35 UTC

    You should look at using HTML::FillInForm to fill out your forms. I use it all the time with HTML::Template with great success.

    Just do something like this:

    my $q = new CGI(); my $template = new HTML::Template( ... ); my $html = $template->output(); my $fif = new HTML::FillInForm; my $output = $fif->fill(scalarref => \$html, fobject => $q);

    That will take your raw HTML, and a CGI query object and find any form fields in your HTML and automatically fill them in (including Select boxes, checkboxes and radio buttons).

    Now you don't have to worry about using HTML::Template to fill in your values so your HTML becomes very simple, and your designers will have less <TMPL_VAR> tags to contend with.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://226148]
Front-paged by gmax
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2014-04-16 23:47 GMT
Find Nodes?
    Voting Booth?

    April first is:

    Results (436 votes), past polls