opi: HTML::Template und "option selected"

Hallo Leute,

auf Grund dieses Threads hier im Archiv habe ich mich ein wenig mit
HTML::Templates beschäftigt. Nun stehe ich schon vor meinem ersten
Problem.

Ich möchte in einem Formular einen Eintrag vorselektieren und habe
zunächst ein kleines Testskript geschrieben:

  
#!/usr/bin/perl -w  
  
use strict;  
use HTML::Template;  
  
my $parm = [];  
my $argv = {};  
  
if ($ENV{REQUEST_METHOD} eq 'GET') {  
   @$parm = split /&/, $ENV{'QUERY_STRING'};  
}  
elsif ($ENV{REQUEST_METHOD} eq 'POST') {  
   read(STDIN, my $env, $ENV{'CONTENT_LENGTH'});  
   @$parm = split /&/, $env;  
}  
  
foreach (@$parm) {  
   my ($name,$value) = split /=/, $_;  
   $name  =~ tr/+/ /;  
   $name  =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;  
   $value =~ tr/+/ /;  
   $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;  
  
   # untaint name and value  
  
   next unless $name =~ /^(\w+)$/;  
   $name = $1;  
  
   next unless $value =~ /^([a-zA-Z_0-9\-, ]+)$/;  
   $value = $1;  
  
   $argv->{$name} = $value;  
}  
  
my $template = HTML::Template->new(filename => '../templates/test_template.tmpl');  
  
my $formular_loop = [];  
my $selected = ();  
  
# die foreach-Schleife ist nur ein Beispiel, statt dessen  
# könnte die Liste aus einer Datei/Datenbank gelesen/selektiert  
# werden  
  
foreach ( 'Audi', 'BMW', 'Ford' ) {  
   if ($argv->{Marke} eq $_) {  
      $selected = 1;  
   }  
   else {  
      $selected = 0;  
   }  
   push @$formular_loop, { value => $_, selected => $selected };  
}  
  
$template->param(formular_loop => $formular_loop);  
  
print "Content-Type: text/html\n\n", $template->output;  

Nun habe ich ein wenig geforscht und nach einem anderen Weg gefunden,
einen Eintrag als selektiert zu markieren. In der foreach-Schleife
prüfe ich jeden Wert, ob er zuvor ausgewählt wurden ist. Gibt es
hier elegantere Methoden, dies zu realisieren? Vielleicht mit
HTML::Template selbst?

Welche Frage mich sonst noch quält ist, dass in dem Archivthread
die Rede davon war, dass es eine klare Trennung von Design und
Programm geben soll. Ok.

Wenn nun statt des Formulars eine Tabelle mit einer Linkliste
ausgegeben werden soll, dann ist doch meine Schleife hinfällig,
da der Key "selected" in dem Template verwendet werden muss,
da mir ansonsten eine Fehlermeldung ausgegeben wird. Also ist man
doch bei einer Strukturänderung dazu gezwungen, auch das Skript
anzupassen. Sehe ich das falsch?

Das ist mein Template (test_template.tmpl):

  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
<html>  
<head>  
   <title>Test Template</title>  
   <link rel="stylesheet" type="text/css" href="/local/css/local.css">  
   <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">  
</head>  
<body>  
<form action="/local/cgi/template.cgi" method="POST">  
   <select name="Marke" size="1">  
      <TMPL_LOOP NAME="formular_loop">  
      <option value="<TMPL_VAR NAME="value">"<TMPL_IF NAME="selected"> selected</TMPL_IF>><TMPL_VAR NAME="value"></option>  
      </TMPL_LOOP>  
   </select>  
   <button type="submit">Absenden</button>  
</form>  
</body>  
</html>  

Greez,
opi

--
Selfcode: ie:( fl:( br:^ va:) ls:] fo:) rl:( n4:? ss:| de:] ch:? mo:|
  1. Tag opi.

    Ich möchte in einem Formular einen Eintrag vorselektieren und habe zunächst ein kleines Testskript geschrieben:

    Soweit so klar, deine Abneigung gegen CGI.pm hast du aber noch nicht abgelegt, oder? ;-)

    Nun habe ich ein wenig geforscht und nach einem anderen Weg gefunden, einen Eintrag als selektiert zu markieren.

    Gesucht oder gefunden?

    In der foreach-Schleife prüfe ich jeden Wert, ob er zuvor ausgewählt wurden ist. Gibt es hier elegantere Methoden, dies zu realisieren? Vielleicht mit HTML::Template selbst?

    Nein, warum auch?

    Welche Frage mich sonst noch quält ist, dass in dem Archivthread die Rede davon war, dass es eine klare Trennung von Design und Programm geben soll. Ok. Wenn nun statt des Formulars eine Tabelle mit einer Linkliste ausgegeben werden soll, dann ist doch meine Schleife hinfällig, da der Key "selected" in dem Template verwendet werden muss, da mir ansonsten eine Fehlermeldung ausgegeben wird.

    Das Script liefert dem Template-Ersteller nur die Daten, nämlich die Automarken und welche vorselektiert wurde. Wie er diese Daten darstellt, ist ihm überlassen. Dazu muss er natürlich wissen, was sich hinter den Variablennamen (in diesem Fall "selected") verbirgt und entsprechend reagieren.

    <select name="Marke" size="1">
          <TMPL_LOOP NAME="formular_loop">
          <option value="<TMPL_VAR NAME="value">"<TMPL_IF NAME="selected"> selected</TMPL_IF>><TMPL_VAR NAME="value"></option>
          </TMPL_LOOP>
       </select>

    Wo ist hier das Problem, das Ganze in eine Liste umzumodeln:

    <ul id="automarken">  
      <TMPL_LOOP NAME="formular_loop">  
        <TMPL_IF NAME="selected">  
          <li class="selektiert">  
        <TMPL_ELSE>  
          <li class="nicht_selektiert">  
        </TMPL_IF>  
        <TMPL_VAR NAME="value">  
        </li>  
      </TMPL_LOOP>  
    </ul>
    

    Du lieferst ja kein HTML aus, sondern nur einen Wert, anhand dessen der Template-Ersteller festlegen kann, wie die Darstellung der Daten erfolgen soll, in meinem obigen Beispiel eben durch Zuweisen einer anderen CSS-Klasse. Wenn du noch Verweise haben willst, dann musst du natürlich dafür sorgen, dass der Ersteller die dafür nötigen Daten geliefert bekommt.

    Du schreibst z.B.:

    <form action="/local/cgi/template.cgi" method="POST">

    Du solltest hier besser schreiben:

    <form action="<TMPL_VAR NAME='script_name'>" method="POST">

    Damit hätte der User eher die Möglichkeit, aus der Auswahlliste eine Linkliste zu machen. Natürlich muss er dazu einer vernünftigen Dokumentation entnehmen können, dass er das Such(?)-Script auch via GET nach dem Schema script.pl?marke=automarke aufrufen kann.

    <ul id="automarken">  
      <TMPL_LOOP NAME="formular_loop">  
        <TMPL_IF NAME="selected">  
          <li class="selektiert">  
        <TMPL_ELSE>  
          <li class="nicht_selektiert">  
        </TMPL_IF>  
        <a href="<TMPL_VAR NAME='script_name'>?marke=<TMPL_VAR NAME='value'>">  
          <TMPL_VAR NAME="value">  
        </a>  
        </li>  
      </TMPL_LOOP>  
    </ul>
    

    Ich hoffe, dich richtig verstanden zu haben :-)

    Siechfred

    1. Hallo Siechfred,

      Tag opi.

      Ich möchte in einem Formular einen Eintrag vorselektieren und habe zunächst ein kleines Testskript geschrieben:

      Soweit so klar, deine Abneigung gegen CGI.pm hast du aber noch nicht abgelegt, oder? ;-)

      hast du das wohlmöglich aus irgendeiner Konversation mit Struppi
      falsch aufgefasst? :-)

      Ich hatte noch nie eine Abneigung gegen CGI.pm. Ganz im Gegenteil.
      Für GD::Graph und fatalsToBrowser war es gut genug. Alles andere
      wollte ich aus Lernzwecken nicht verwenden. Wenn ich es von Anfang an
      verwendet hätte, könnte ich jetzt keine Templates schreiben.

      Jetzt würde ich es verwenden, aber die klare Trennung von Skript und
      HTML/Design halte ich für sehr sinnvoll. Bisher musste ich immer
      beides machen. Ich habe die Skripts entwickelt und auch das Design.
      Ist doch toll, wenn ich jetzt etwas davon an jemanden abtreten
      kann :-)

      Ausserdem, was spricht denn gegen die Verwendung von HTML::Template?

      Das einzige, was mich daran stört ist, dass man sich vorher manche
      Hashes mühselig zusammenstricken muss. Aber damit kann ich leben.

      Das Script liefert dem Template-Ersteller nur die Daten, nämlich die Automarken und welche vorselektiert wurde. Wie er diese Daten darstellt, ist ihm überlassen. Dazu muss er natürlich wissen, was sich hinter den Variablennamen (in diesem Fall "selected") verbirgt und entsprechend reagieren.

      <select name="Marke" size="1">
            <TMPL_LOOP NAME="formular_loop">
            <option value="<TMPL_VAR NAME="value">"<TMPL_IF NAME="selected"> selected</TMPL_IF>><TMPL_VAR NAME="value"></option>
            </TMPL_LOOP>
         </select>

      Wo ist hier das Problem, das Ganze in eine Liste umzumodeln:

      <ul id="automarken">

      <TMPL_LOOP NAME="formular_loop">
          <TMPL_IF NAME="selected">
            <li class="selektiert">
          <TMPL_ELSE>
            <li class="nicht_selektiert">
          </TMPL_IF>
          <TMPL_VAR NAME="value">
          </li>
        </TMPL_LOOP>
      </ul>

      
      >   
      > Du lieferst ja kein HTML aus, sondern nur einen Wert, anhand dessen der Template-Ersteller festlegen kann, wie die Darstellung der Daten erfolgen soll, in meinem obigen Beispiel eben durch Zuweisen einer anderen CSS-Klasse. Wenn du noch Verweise haben willst, dann musst du natürlich dafür sorgen, dass der Ersteller die dafür nötigen Daten geliefert bekommt.  
        
      Okay, du hast vollkommen recht.  
        
      
      >   
      > Du schreibst z.B.:  
      >   
      > > <form action="/local/cgi/template.cgi" method="POST">  
      >   
      > Du solltest hier besser schreiben:  
      >   
      > `<form action="<TMPL_VAR NAME='script_name'>" method="POST">`{:.language-html}  
        
      Ok, das werde berücksichtigen. Aber das war ja auch nur ein Beispiel.  
        
      
      > Ich hoffe, dich richtig verstanden zu haben :-)  
        
      Jawohl. Danke dir.  
        
      Greez,  
      opi
      
      -- 
      Selfcode: ie:( fl:( br:^ va:) ls:] fo:) rl:( n4:? ss:| de:] ch:? mo:|