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

hi, i need to define html::template from the following hash.
%add=( hash1=>{ name=>"name1 ", type =>"text", default=>" " value=[""], entries=>"M". }, hash2=>{ name=>"name2 ", type=>"dropdown", req=>"prc", default=>" " value=["value1","value2","value3"], entries=>" " } );
I need to define text box if the type is text ie if type=>"text",and if the type is dropdown ie tpe=>"dropdown",i need to define select option using the name and value pairs dynamically.I need to define template using name and value pairs from the below hash.name is used to define text box or select option name ie label and value refers to its values.can any body suggest me how to define html template for this hash. Text box may contain default value when it is present in default=>"some value" ,need to show the default value to user and in the case of select option default=>"some value ",refers to selected in select option menu.If the enteries=>"more" means i need to define text area instead of text. can any one suggest me how to define HTML:: template for this hash. Thanks, srins.

Replies are listed 'Best First'.
Re: how to define html::template for the following hash in perl/cgi
by friedo (Prior) on Nov 04, 2005 at 14:03 UTC
    It looks to me like your needs would better be served by an array of hashes. You could change your structure to:

    my @add=( { name=>"name1 ", type =>"text", default=>" " value=[""], entries=>"M". }, { name=>"name2 ", type=>"dropdown", req=>"prc", default=>" " value=["value1","value2","value3"], entries=>" " } );

    Then it's just a simple matter of sending the arrayref to your template:

    $tmpl->param( blah => \@add );

    And then defining a template loop. Take a look at the HTML::Template docs for how to make a loop and use conditionals.

      Actually, the structure doesn't need to change at all, if the hash keys don't matter much (which they don't appear to). Just "cast" your hash of hashes into an array of hashes, like this:

      $tmpl->param( blah => [ values %add ] );

      The values piece generates a list containing the values (which are your inner hashes) inside %add; the square brackets make that list into an ARRAYref for the use of HTML::Template.

      Or, if you need to preserve the key value, you could create a map:

      $tmpl->param( blah => [ map { { %{$add{$_}}, 'key' => $_ } } keys %add + ] );

      That's a little hairy, so let me explain: the map returns a list of HASHrefs. Each of these comes from your %add hash, and is modified with a new member called 'key' with the value of the %add hash's key for the given element. Yes, that's still confusing. Here's what the resulting data structure looks like:

      $VAR1 = [ { 'req' => 'prc', 'value' => [ 'value1', 'value2', 'value3' ], 'entries' => ' ', 'name' => 'name2 ', 'type' => 'dropdown', 'default' => ' ', 'key' => 'hash2' }, { 'value' => [ '' ], 'entries' => 'M', 'name' => 'name1 ', 'type' => 'text', 'default' => ' ', 'key' => 'hash1' } ];
      <-radiant.matrix->
      A collection of thoughts and links from the minds of geeks
      The Code that can be seen is not the true Code
      "In any sufficiently large group of people, most are idiots" - Kaa's Law
        $tmpl->param( blah => [ values %add ] );

        That has the disadvantage of ending up with an unknown order of values, and my assumption (based on the hash key names) was that the OP wanted an ordered list. One could certainly do this, though:

        $tmpl->param( blah => [ map { $add{$_} } sort keys %add ] )
Re: how to define html::template for the following hash in perl/cgi
by amw1 (Friar) on Nov 04, 2005 at 15:45 UTC
    Not to be dense, but why do you need to re-write the hash? You did all the work to build it, why should your templating system not handle it? I used HTML::Template a few years ago and am actually surprised that this type of thing continues to be an issue. I can't help much with H::t but here is the TemplateToolkit foo to do it. (showing another available option)
    [% FOREACH element = add.keys %] [% IF add.$element.type == "text" %] <input type="text" name="[% add.$element.name %]" value="[% add.$e +lement.default %]"> [% ELSIF add.$element.type == "dropdown" %] <select name="[% add.$element.name %]"> [% FOREACH option = add.$element.value %] <option value="[% option %]"> [% option %] </option> [% END %] </select> [% END %] <br> [% # put a line break between the form elements %] [% END %]
    In your perl code you would just pass the add hash into the TemplateToolkit process routine.
      hi thanks for your suggestion i tried to pass the hash of hashes i constructed
      as $template->process($file,%add) || die $template->error(); for my hash my %add=( hsh1=>{ name=>"name1 ", type =>"text", default=>" ", value=>[" "], entries=>"M" }, hsh2=>{ name=>"name2 ", type=>"dropdown", req=>"prc", default=>" ", value=>["value1","value2","value3"], entries=>" " } ); for your code [% FOREACH element = add.keys %] [% IF add.$element.type == "text" %] <input type="text" name="[% add.$element.name %]" value="[% add.$e +lement.default %]"> [% ELSIF add.$element.type == "dropdown" %] <select name="[% add.$element.name %]"> [% FOREACH option = add.$element.value %] <option value="[% option %]"> [% option %] </option> [% END %] </select> [% END %] <br> [% # put a line break between the form elements %] [% END %]
      but i get following error, Content-type: text/html Can't use string ("hsh2") as a HASH ref while "strict refs" in use at /usr/cisco/packages/perl/perl-5.8.6/lib/site_perl/5.8.6/sun4-solaris/Template/Service.pm line 79. i also tried to pass the reference as $template->process($file,\%add) || die $template->error(); but nothing is substituted in the html file.can u help me how to pass my hash to the html file or i need to change the above code.please help me in this regard. Thanks, srins.