4

What is the "modern Perl" recommended way to generate HTML dynamically?

I used to be able to just use CGI::tag ( @attr ), but seems this is deprecated now. However, reading through CGI::Alternatives, I only see examples using static HTML.

I suppose under Template::Toolkit, I would use something like [% html %], but that still leaves the problem of generating the corresponding $html string. I'm looking for a library, like CGI, that generates correct HTML tags, with correct escaping, knows about self-closing tags, etc, and is not being deprecated ... unless there is a way of doing things in modern Perl web frameworks that supersedes this altogether.

EDIT:

Some examples:

  • How do I generate the HTML for a dropdown (<select>) when the values and labels are only known at run-time? The CGI method was just 1 line: $q->popup_menu ({ name => $name, values => \@values, labels => \%labels }); The Template::Toolkit method involves so many lines of code (here is an example) ... isn't there another way?
  • How do I generate the HTML for a tag whose attributes are not known until run-time? In CGI it's just $q->tag ( \%attr ); ... what is the Template::Toolkit equivalent?
  • How do I generate HTML when a list of tags and their content is not known until run-time? In CGI it's: $q->parent ( \%attr, @child ); ... how is this done in Template::Toolkit? I realize this is kind of vague, but I deal with situations where large amounts of content are not known until run-time, so coming up with a template in advance seems untenable to me, but I may not be aware of some advanced features of Template::Toolkit.
  • I have more complicated cases to deal with as well, such as involving recursion, but if I get the above sorted out, then the rest might fall into place.
Arnon Weinberg
  • 871
  • 8
  • 20
  • 2
    Perhaps you should describe exactly what *you* have in mind by *Dynamic HTML*? It is an imprecise term that means different things to different people. And you shouldn't be waiting until run time to generate fixed markup. There are plenty of HTML editors that will look after keeping what you write well-formed, and you can create the necessary HTML that way and hand it as a template file to `Template::Toolkit` to insert any parameterised sections. You could do the same with the CSS and JavaScript files, but I suggest that those should remain static – Borodin Aug 18 '15 at 23:29
  • OK, I guess that question gives me a hint that generating HTML at run-time is maybe not a common practice. I'll see what I can do to clarify my question. – Arnon Weinberg Aug 19 '15 at 06:00
  • I've moved to `Mojolicious` - but it's a bit of a different mindset, as it 'runs' as a standalone app. – Sobrique Aug 20 '15 at 15:57
  • @Sobrique, I know Mojo has a different templating system than TT, but does it have a way to generate HTML dynamically in place of CGI? – Arnon Weinberg Aug 20 '15 at 18:37
  • Yes. You can mix perl and html to do for example a table from an array. – Sobrique Aug 20 '15 at 19:29
  • @Sobrique, can you give an example? I can mix Perl and HTML in TT as well, but still need something better than "print '';" to generate HTML... Is there a link to documentation on generating HTML dynamically in Mojo? – Arnon Weinberg Aug 20 '15 at 20:25
  • Example posted. There's lots of docs on Mojolicious - almost too much IMO. – Sobrique Aug 20 '15 at 20:52

2 Answers2

4

Personally, I'd build the HTML in the template in the same way as the <select> example that you give. The idea is that by separating it out into template that only contain HTML and a small amount of TT code, then it becomes easier for a front-end developer to edit the code without having to know Perl. And I really don't think it's as complex as you make it out to be:

<select name="[% select.name %]">
[% FOREACH option IN select.options -%]
  <option value="[% option.value %]">[% option.text %]</option>
[% END -%]
</select>

But I also hear people talking about libraries like HTML::FormFu. Something like that might be what you're looking for.

Update: Got bored at lunch and wrote a tag/attribute example:

<tag [% FOREACH p IN attr.pairs; p.key %]="[% p.value %]" [% END %]>

(Assumes that attr is a hash of attribute names and values).

Which got me thinking that writing a library of these TT macros really wouldn't be hard.

Dave Cross
  • 68,119
  • 3
  • 51
  • 97
  • Re – Arnon Weinberg Aug 19 '15 at 17:19
4

Mojolicious is what I've adopted since stopping using CGI.

A very basic sample of how you could pass an array through into some HTML. You can do more dynamic things with it - from static content all the way to completely on the fly.

A very basic example looks a bit like this:

#!/usr/bin/perl

use strict;
use warnings;
use Mojolicious::Lite;

get '/' => sub {
    my ( $mojo ) = @_; 

    my @stuff = qw ( fish carrot egg spoon banana ); 
    $mojo -> stash ( 'stuff' => \@stuff ); 
    $mojo -> render (template => 'index' );
};

app -> start;

__DATA__
@@index.html.ep

<BODY>
  <TABLE BORDER=1>
      % foreach my $value ( @{ stash('stuff') } ) {
      <TR><TD> <%= $value %></TR></TD>
      % }
  </TABLE>
</BODY> 

You can pass arbitrary variables in via the stash to a template - in this case we pass an array ref.

Couple of caveats - it can actually be a bit overkill for a 'simple' CGI - it's pretty powerful, and runs off it's own process - morbo for dev (defaults to :3000 - auto reloads when you change the script) and hypnotoad for prod (defaults to :8080).

This suits me fine, because I run nginx as a reverse proxy, and redirect - so I can fiddle about with a "dev" instance, to my heart's content, and just swap ports and runners when I'm ready to go 'live'.

You can pick out things passed in to your script via param (this picks out either GET parameters or POST parameters.)

Sobrique
  • 52,974
  • 7
  • 60
  • 101