Minimales Modul

Das Forum soll der Ablage von Lösungen für immer wieder auftauchende Problemstellungen dienen. // This forum contains solutions to problems that frequently occur.
Benutzeravatar
fliegermichl
Beiträge: 114
Registriert: 29.01.2008, 11:51:45
Wohnort: Echzell

Minimales Modul

Beitrag von fliegermichl » 08.08.2008, 10:45:35

Hallo Christian,

nach einiger Zeit versuche ich mich erneut am apf und bringe einfach nichts brauchbares zustande damit.
Vielleicht können wir an dieser Stelle mal ein einfaches (aber dennoch vollständiges und den Regeln des Frameworks folgendes) Modul Schritt für Schritt aufbauen?

Ich denke da zum Beispiel an einen einfachen Rechner. Dieser soll zwei Operanden und einen Operator haben. Ein Controller soll die Berechnung durchführen und Fehler feststellen und in einem Template das Ergebnis sowie die zuletzt eingegeben Werte wieder ausgeben.

An geeigneter Stelle soll dieser Rechner zwei mal in eine Hallo Welt Webseite eingebunden werden. Dann kann man auch den linkHandler verwenden um zu demonstrieren, wie sich mehrere Instanzen ein und desselben Modules implementieren und verwenden lassen.

Ich denke, ein derartiges Modul erleichtert es dem Anfänger zu verstehen, wie das Framework funktioniert. Die z.Zt. vorhandenen Tutorials halte ich für zu umfangreich als das diese von einem Anfänger verinnerlicht werden können.

Die Dokumentation ist sicherlich vollständig und richtig, meiner Ansicht nach hast Du aber ein Talent dafür einfache Zusammenhänge so kompliziert zu beschreiben, daß man Mühe hat es zu verstehen (ich habe an anderer Stelle gelesen, daß Du den Doktor Titel von Freunden bekommen hast. Ob das wohl die Ursache ist? :D )

Viele Grüße
Michl

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 08.08.2008, 11:46:01

Hallo fliegermichl,
Vielleicht können wir an dieser Stelle mal ein einfaches (aber dennoch vollständiges und den Regeln des Frameworks folgendes) Modul Schritt für Schritt aufbauen?
Gerne. Wichtigstes Element beim Thema "einfach" ist das Feedback. Wir können also gerne diesen Thread als Tutorial für das Erstellen eines "einfachen Moduls" verwenden, bei dem ich ein Vorgehen vorstelle und du (oder wer auch immer) einfach an den entsprechenden Stellen nachfragt. Einverstanden?
(Ich habe an anderer Stelle gelesen, daß Du den Doktor Titel von Freunden bekommen hast. Ob das wohl die Ursache ist? :D )
Ich vermute, das ist die Ursache - ja! :D


1. Anforderung:
Ich denke da zum Beispiel an einen einfachen Rechner. Dieser soll zwei Operanden und einen Operator haben. Ein Controller soll die Berechnung durchführen und Fehler feststellen und in einem Template das Ergebnis sowie die zuletzt eingegeben Werte wieder ausgeben.
Das scheint mir ein einfaches Beispiel zu sein. Konkret denke ich bei dem Satz an ein Formular mit vier Elementen:
  • Eingabe-Feld Operand1: Eingabe einer beliebigen Zahl
  • Eingabe-Feld Operator: Select-Feld für die Auswahl des Operanden (+,-,*,/)
  • Eingabe-Feld Operand2: Eingabe einer beliebigen Zahl
  • Button Berechnen: Abschicken des Formulars
Die Ausgabe könnte man nun direkt unterhalb des Formulars einbauen, sofern die Eingabe als korrekt erachtet wird oder das Formular ausblenden, wenn die Eingabe ok ist und nur das Ergebnis darstellen. Sollten wir uns für letzteres entscheiden macht es Sinn, einen Link auf das Formular einzubauen.


2. Vorgehensweise:
Das Modul besteht im einfachsten Fall aus einer Template- und einer Controller-Datei. Um das Modul aufrufen zu können, legen wir zusätzlich noch eine Bootstrap-Datei (index.php) an. Ist das Modul fertig, bauen wir es per Tag einfach in eine bestehende Seite (z.B. in die Spielwiese des Demo-Projekts - siehe http://adventure-php-framework.org/fron ... 8-php5.zip) ein.


3. Umsetzung

3.1. Download & Installation
Ich gehe davon aus, dass sich auf dem Rechner, auf dem du entwickeln möchtest lediglich dein präferierter Editor und ein Webserver mit geladenem PHP-Modul installiert ist. Um mit der Entwicklung beginnen zu können, muss der Quellcode des Frameworks auf dem lokalen Rechner verfügbar sein. Hierzu ist folgende Vorgehensweise sinnvoll:
Mit diesen Schritten ist die Installation abgeschlossen und wir können uns der Erstellung des Moduls widmen.


3.2. Erstellen der Modul-Struktur
Aus Erfahrung hat es sich bewährt, Software-Teile in seine Zuständigkeitsbereiche gegliedert abzulegen. Konkret bedeutet das, Teile der Präsentationsschicht in einem Ordner pres, Teile der Business-Schicht in einem Ordner biz und Teile der Datenschicht in einem Ordner data abzulegen. In unserem Fall (und wir wollen es ja einfach halten, was zwar nicht ganz sauber ist, aber eben einfach :D ) benötigen wir nur einen Ordner pres. Diesen wiederum unterteilen wir in die Ordner documentcontroller und templates, in denen wir die oben erwähnte Controller. und Template-Datei ablegen. Unser Modul nennen wir calc. Der Name wird gleichzeitig der Name des Basis-Ordners (Namespace) des Moduls sein. Es ergibt sich damit folgende Ordnerstruktur:

Code: Alles auswählen

apf/
     apps/
             core/
             modules/
                          calc/
                                 pres/
                                        documentcontroller/
                                        templates/
             tools/

3.3. Erstellen der Modul-Dateien
Um ein erstes Erfolgserlegbnis zu haben, legen wir zunächst nur eine Template-Datei mit dem Namen calc.html im Ordner apf/modules/calc/pres/templates/ an. Dieser Datei geben wir den Inhalt

Code: Alles auswählen

Hier entsteht ein APF-Rechner!
speichern und schließen diese. Die Template-Datei des Moduls dient uns nun während der Entwicklung als Basis-Template, später wird das Template einfach per <core:importdesign /> am gewünschten Platz in eine bestehende Webseite eingebunden.


3.4. Anlegen der Bootstrap-Datei (index.php)
Um das Modul (aktuell ein statisches Template) aufrufen/anzeigen zu können, bedarf es einer PHP-Datei, die via HTTP erreichbar ist (Bootstrap-Datei). Diese nennen wir der Einfachheit wegen index.php und legen diese unter apf/ an. Der Inhalt der Datei kann aus dem Hallo Welt!-Tutorial kopiert werden und sieht wie folgt aus:

Code: Alles auswählen

include_once('./apps/core/pagecontroller/pagecontroller.php');
$Page = new Page('calc');
$Page->loadDesign('modules::calc::pres::templates','calc');
echo $Page->transform(); 
Die einzelnen Zeilen im Detail:
  • Zeile 1: Der PageController wird eingebunden. Dieser ist eine der zentralen Komponenten des Frameworks und erstellt die Umgebung, in der das Framework ausgeführt wird.
  • Zeile 2: Eine Instanz der Klasse Page (zentrale Klasse des PageControllers) wird erstellt. Das übergebene Argument ist optional und definiert lediglich den Namen der erstellten Seite.
  • Zeile 3: Mit der Methode loadDesign() wird das initiale Template geladen. Wie bereits erwähnt, nutzen wir hier direkt das Template des Moduls. Im Fall einer Webseite, würde an dieser Stelle das Basis-Template der Webseite eingesetzt werden.
  • Zeile 4: Nach dem in der vorherigen Zeile aus dem Basis-Template der interne Objektbaum aufgebaut wurde, kann die Seite nun transformiert werden. Da die Methode transform() den transformierten Inhalt der Seite ausgibt, kann dieser per echo an den Browser gesendet werden.
Rufen wir nun die Datei index.php im Browser auf (falls der Ordner apf direkt im DOCUMENT_ROOT angelegt wurde gilt die URL http://localhost/apf/index.php), so sollte der Inhalt des oben angelegten Templates erscheinen:
Hier entsteht ein APF-Rechner!
Viele Grüße,
Christian

Benutzeravatar
fliegermichl
Beiträge: 114
Registriert: 29.01.2008, 11:51:45
Wohnort: Echzell

Re: Minimales Modul

Beitrag von fliegermichl » 08.08.2008, 14:30:50

Hallo Christian,

perfekt!
nachdem ich das Modul bis hierher nachvollzogen habe, erscheint folgerichtig

"Hier entsteht ein APF Rechner!"

Nun habe ich die Dokumentation nach den Formularfunktionen durchsucht und kam zu folgendem Ergebnis
Datei modules/calc/pres/templates/calc.html

Code: Alles auswählen

<html:form name="CalcForm" method="post" action="">
    <form:placeholder name="Operand1Error" />
    Operand1: <form:text name="operand1" class="eingabe_feld" validate="true" button="docalc" />
    Operation: <form:multiselect name="operations[]" />
    <form:placeholder name="operand2error" />
    Operand2: <form:text name="operand2" class="eingabe_feld" validate="true" button="docalc" />
    <br />
    <form:button name="docalc" value="Berechnen" />
</html:form>
Lasse ich mir die Seite jetzt anzeigen, erscheint "Operator1: Operation: Operator2:" als einfacher Text. Schaue ich in den Quelltext, so steht hier exakt der Quelltext der Datei darin. Offenbar fehlt hier das Einbinden des Parsers und irgendwo muss wohl noch der Controller bemüht werden, welcher die verfügbaren Operationen dazugibt.

Viele Grüße
Michl

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 08.08.2008, 17:11:52

Hallo fliegermichl,
perfekt!
Schön, dass es dir gefällt.
Nun habe ich die Dokumentation nach den Formularfunktionen durchsucht und kam zu folgendem Ergebnis
Datei modules/calc/pres/templates/calc.html
Ich wollte mit dem Formular heute Abend fortfahren, da du aber schon vorgearbeitet hast, hier gleich die Auflösung: :)


3.5. Erweiterung des Templates
Die Form-TagLib muss zur Verwendung erst eingebunden werden. Siehe hierzu http://adventure-php-framework.org/Seite/011-Formulare, Kapitel 1. In deiner Template-Definition fehlt also ein

Code: Alles auswählen

<core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
Weiterhin wird für die Ausgabesteuerung ein Controller benötigt, der das Formular und/oder eben das Ergebnis darstellt. Zunächst spezifizieren wir im Template per

Code: Alles auswählen

<@controller namespace="modules::calc::pres::documentcontroller" file="calc_controller" class="calc_controller" @>
dass beim Transformieren des aktuellen DOM-Knotens der DocumentController calc_controller damit betraut werden soll, die Ausgabe des Views dynamisch zu steuern. Hiermit ist die Definition des Templates zunächst abgeschlossen. Es ergibt sich insgesamt folgender Datei-Inhalt:

Code: Alles auswählen

<@controller namespace="modules::calc::pres::documentcontroller" file="calc_controller" class="calc_controller" @>
<core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
<html:form name="CalcForm" method="post" action="">
    <form:placeholder name="Operand1Error" />
    Operand1: <form:text name="operand1" class="eingabe_feld" validate="true" button="docalc" />
    Operation: <form:multiselect name="operations[]" />
    <form:placeholder name="operand2error" />
    Operand2: <form:text name="operand2" class="eingabe_feld" validate="true" button="docalc" />
    <br />
    <form:button name="docalc" value="Berechnen" />
</html:form>
3.6. Definition des Controllers
Ein APF-DocumentController erbt stets von der Klasse baseController (Basis-Klasse die der PageController bereitstellt) und implementiert die Interface-Methode transformContent(). Der Rumpf des für unser Modul verwendeten Controllers hat damit folgende Gestalt:

Code: Alles auswählen

   class calc_controller extends baseController
   {
      function calc_controller(){
      }

      function transformContent(){
      }

   }
Die Klasse wird gemäß unserer Definition im Template in der Datei calc_controller.php im Ordner modules/pres/documentcontroller/ erwartet und trägt den Namen calc_controller. Die drei genannten Parameter können entsprechend den Attributen namespace, file und class innerhalb der Definition des DocumentControllers des Templates beeinflusst werden.

Rufen wir nun die URL http://localhost/apf/ auf, wird eine leere Seite angezeigt. Dies ist auch korrekt so, denn die Implementierung unseres Controllers weist noch keine Aktionen auf. Im nächsten Kapitel kümmern wir uns um die Ausgabe des Formulars.


3.7. Ausgabe des Formulars
Zur Ausgabe des Formulars muss die Methode transformContent() erweitert werden. Wie in der Dokumentation (siehe http://adventure-php-framework.org/Seite/011-Formulare, Kapitel Kapitel 1, Ende) beschrieben kann innerhalb des DocumentControllers über die private Methode __getForm() auf das Formular-Objekt zugegriffen werden. Zur Ausgabe stehen zwei Möglichkeiten zur Verfügung, wobei wir hier der Einfachheit halber das TransformOnPlace-Feature nutzen, mit dem das Formular an der Stelle der Definition im Template ausgegeben werden kann. Kopieren wir das Beispiel aus der Dokumentation in die transformContent()-Methode und passen es an unsere Anforderung an, beinhaltet die Datei calc_controller.php nun folgendes:

Code: Alles auswählen

   class calc_controller extends baseController
   {
      function calc_controller(){
      }

      function transformContent(){
         $Form__CalcForm = &$this->__getForm('CalcForm');
         $Form__CalcForm->transformOnPlace();
      }

   }
Nach einem erneuten Aufruf der URL http://localhost/apf/ wird das Formular wie gewünscht angezeigt.

Die Frage ist nun: Warum muss man zur Verarbeitung eines Formulars immer einen Controller definieren? Antwort: Da ein Formular immer eine Aktion nach sich zieht, in der ein Controller involviert sein muss! Letzteres ist auch der Grund, warum Formulare nicht direkt ausgegeben werden, sondern erst eine Controller-Aktion (in diesem Fall der Aufruf der Methode transformOnPlace()) zur Ausgabe notwenig ist.


3.8.Erweiterung des Formulars
Das oben gezeigte Formular muss nun mit den gewünschten Operanden gefüllt werden. Dies kann im Controller oder direkt im Template erfolgen. Da die Operanden in diesem Beispiel der Einfachheit wegen statisch sind, spricht nichts gegen eine Definition im Template. Das Select-Control wird damit wie folgt erweitert (Details können dem Kapitel 2.4.14. Select-Feld mit Optionen unter http://adventure-php-framework.org/Seit ... rd-TagLibs entnommen werden):

Code: Alles auswählen

<html:form name="CalcForm" method="post" action="">
    <form:placeholder name="Operand1Error" />
    Operand1: <form:text name="operand1" class="eingabe_feld" validate="true" button="docalc" />
    Operation:
    <form:select name="operation">
       <select:option value="plus">+</select:option>
       <select:option value="minus">-</select:option>
       <select:option value="dividieren">/</select:option>
       <select:option value="multiplizieren">*</select:option>
    </form:select>
    <form:placeholder name="operand2error" />
    Operand2: <form:text name="operand2" class="eingabe_feld" validate="true" button="docalc" />
    <br />
    <form:button name="docalc" value="Berechnen" />
</html:form>
Bei Aufruf des Projektes kann nun ein Operand aus der Liste der vier Möglichkeiten ausgewählt werden.


Als nächstes ist Formular-Validierung und Plausibilitätsprüfung an der Reihe. Da das beim letzten Mal so gut geklappt hat, würde ich sagen: jetzt bist du dran! ;)
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 08.08.2008, 23:19:28

Hallo fliegermichl,

als ich das Beispiel in meiner Entwicklungsumgebung erweitert habe, bin ich auf einen Bug gestoßen, dass der Wert "0" im Formular nicht mehr automatisch übernommen wird. Hier funktioniert das Presetting nicht korrekt. Um sicher zu gehen, dass du bei der Implementierung nicht über dieses Phänomen stolperst, schau bitte kurz in den Thread Presetting von Formularwerten beim Wert "0" fehlerhaft und lade das entsprechende Patch-Set herunter.


3.9. Validierung der Eingaben und Berechnung des Ergebnisses
Die Validierung der Eingaben beschränkt sich auf den Fall Division, da nur dort ein echter Fehler auftreten kann. Zur Ausgabe des Hinweises, bzw. des Ergebnisses wird der Platzhalter operand2error genutzt. Dieser kann mit Hilfe der Methode setPlaceHolder() gefüllt werden. Damit das Formular nur dann validiert wird, wenn es auch abgesendet ist, muss im Controller eine weitere Kontrollstruktur eingeführt werden. Ob ein Formular abgesendet wurde kann dabei per

Code: Alles auswählen

$Form__CalcForm = &$this->__getForm('CalcForm');
if($Form__CalcForm->get('isSent')){
   echo 'Formular wurde abgesendet!';
}
else{
   echo 'Formular wurde nicht abgesendet!';
}
geprüft werden. Liegt der Fall "abgesendet" vor, so können die Werte der Felder wie folgt ausgelesen werden:

Code: Alles auswählen

$Operand1 = &$Form__CalcForm->getFormElementByName('operand1');
$Value1 = (int)$Operand1->getAttribute('value');
$Operand2 = &$Form__CalcForm->getFormElementByName('operand2');
$Value2 = (int)$Operand2->getAttribute('value');
Die Variable $Form__CalcForm beinhaltet dabei eine Referenz auf das Formular-Objekt. Um den aktuellen Operanden aus dem Selekt-Feld auszulesen, kann folgender Code-Schnipsel genutzt werden:

Code: Alles auswählen

$Operator = &$Form__CalcForm->getFormElementByName('operation');
$CurrentOperator = &$Operator->getSelectedOption();
$OperaturType = $CurrentOperator->getAttribute('value');
Hierbei wird zuerst eine Referenz auf das Selekt-Feld erzeugt, anschließend per getSelectedOption() eine Referenz auf das aktuell selektierte Option-Objekt, von dem im dritten Schritt dann der Inhalt ausgelesen wird. Die hier relevanten Methoden und Objekte können in der API-Dokumentation bzw. auf der Formular-Dokumenationsseite nachgelesen werden.

Zusammangefasst kann die Validierung der Eingaben und die Berechnung des Ergebnisses mit folgendem Controller-Code erzeugt werden:

Code: Alles auswählen

   class calc_controller extends baseController
   {

      function calc_controller(){
      }

      function transformContent(){

         // Formular-Objekt referenzieren
         $Form__CalcForm = &$this->__getForm('CalcForm');

         // Eingaben prüfen
         if($Form__CalcForm->get('isSent')){

            // Eingaben auslesen
            $Operand1 = &$Form__CalcForm->getFormElementByName('operand1');
            $Value1 = (int)$Operand1->getAttribute('value');
            $Operand2 = &$Form__CalcForm->getFormElementByName('operand2');
            $Value2 = (int)$Operand2->getAttribute('value');
            $Operator = &$Form__CalcForm->getFormElementByName('operation');
            $CurrentOperator = &$Operator->getSelectedOption();
            $OperaturType = $CurrentOperator->getAttribute('value');

            // Auf Division durch 0 prüfen
            if($OperaturType == 'dividieren' && intval($Value2) === 0){
               $Form__CalcForm->setPlaceHolder('operand2error','Fehler: Unerlaube Operation (Division durch Null)!');
             // end if
            }
            else{

               // Ergebnis errechnen
               $Value1 = (int)$Operand1->getAttribute('value');
               $Value2 = (int)$Operand2->getAttribute('value');

               if($OperaturType == 'plus'){
                  $Result = $Value1 + $Value2;
                // end if
               }
               elseif($OperaturType == 'minus'){
                  $Result = $Value1 - $Value2;
                // end elseif
               }
               elseif($OperaturType == 'dividieren'){
                  $Result = $Value1 / $Value2;
                // end elseif
               }
               else{
                  $Result = $Value1 * $Value2;
                // end else
               }

               // Ergebnis darstellen
               $Form__CalcForm->setPlaceHolder('operand2error','Ergebnis der Berechnung: '.$Result);

             // end else
            }

          // end if
         }

         // Formular darstellen
         $Form__CalcForm->transformOnPlace();

       // end function
      }

    // end class
   }
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 09.08.2008, 10:56:58

3.10. Templates zur Ausgabe
Um die bisher direkt im Controller definierte Ausgabe durch den Template-Bauer manipulierbar zu gestalten, lagern wir diese nun aus. Dabei ist der Entwickler frei, im Template diverse Templates (<html:template />) zu definieren und im Controller zu adressieren und zu verwenden. In unserem Fall gibt es zwei Anwendungsfälle für Templates: Ausgabe der Fehlermeldung bei Division durch Null und Ergebnis der Berechnung. Die Vorgehensweise ist dabei recht einfach: der Inhalt, der bisher direkt im Controller ausgegeben wurde, wird nun aus der Ausgabe eines Templates bezogen.

Dazu legen wir zunächst im Template zwei neue Templates an:

Code: Alles auswählen

<html:template name="Result">
  Das Ergebnis der Berechung ist: <strong><template:placeholder name="Result" /></strong>
</html:template>

<html:template name="Error">
  <font style="color: red; font-weight: bold;">Unerlaube Operation (Division durch Null)!</font>
</html:template>
Das Template mit dem Namen Result dient zur Ausgabe des Ergebnisses, Error zur Ausgabe der Fehlermeldung. Ersteres enthält einen Platzhalter, der zur Ausgabe des Rechenergebnisses genutzt wird.

Im Controller müssen nun die Ausgabestellen angepasst werden. Dazu ersetzen wir im Fall "Fehler-Ausgabe" die Zeile

Code: Alles auswählen

$Form__CalcForm->setPlaceHolder('operand2error','Fehler: Unerlaube Operation (Division durch Null)!');
durch

Code: Alles auswählen

$Template__Error = &$this->__getTemplate('Error');
$Form__CalcForm->setPlaceHolder('operand2error',$Template__Error->transformTemplate());
In der ersten Zeile wird das Template-Objekt mit dem Namen Error referenziert und in der zweiten Zeile setzen wir die Ausgabe des Template-Objektes in den Formular-Platzhalter ein.

Gleiche Vorgehensweise wird auch beim Anzeigen des Ergebnisses gewählt, mit dem Unterschied, dass vor der Ausgabe des Templates noch der Ergebnis-Platzhalter gefüllt werden muss. In diesem Fall ersetzen wir

Code: Alles auswählen

$Form__CalcForm->setPlaceHolder('operand2error','Ergebnis der Berechnung: '.$Result);
durch

Code: Alles auswählen

$Template__Result = &$this->__getTemplate('Result');
$Template__Result->setPlaceHolder('Result',$Result);
$Form__CalcForm->setPlaceHolder('operand2error',$Template__Result->transformTemplate());
Wie in der zweiten Zeile zu sehen ist, kann per setPlaceHolder() der Wert eines Platzhalters eines Templates befüllt werden.


3.11. Vorbereitung für den Einbau in eine bestehende Seite
Um das Modul für den Einbau in eine bestehende Seite vorzubereiten, legen wir einen div um das Formular und fügen einige Formatierungen hinzu. Aus Gründen der Einfachheit verwenden wir hier dedizierte style-Angaben statt ausgelagerte CSS-Dateien. Es ergibt sich damit folgender Inhalt der Template-Datei:

Code: Alles auswählen

<@controller namespace="modules::calc::pres::documentcontroller" file="calc_controller" class="calc_controller" @>
<core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />

<div style="border: 2px solid black; background-color: #eeeeee; width: 240px; height: 180px; padding: 5px; font-family: Arial, Helvetica, sans-serif; font-size: 11px;">

  <font style="font-size: 16px; font-weight: bold;">APF-Modul "calc"</font>
  <br />
  <br />
  <html:form name="CalcForm" method="post" action="">
    <form:placeholder name="Operand1Error" />
    Operand1: <form:text name="operand1" validate="true" button="docalc" validator="Number"/>
    <br />
    Operation:
    <form:select name="operation">
      <select:option value="plus">+</select:option>
      <select:option value="minus">-</select:option>
      <select:option value="dividieren">/</select:option>
      <select:option value="multiplizieren">*</select:option>
    </form:select>
    <br />
    Operand2: <form:text name="operand2" validate="true" button="docalc" validator="Number"/>
    <br />
    <br />
    <form:button name="docalc" value="Berechnen" />
    <br />
    <br />
    <form:placeholder name="operand2error" />
  </html:form>

</div>

<html:template name="Result">
  Das Ergebnis der Berechung ist: <strong><template:placeholder name="Result" /></strong>
</html:template>

<html:template name="Error">
  <font style="color: red; font-weight: bold;">Unerlaube Operation (Division durch Null)!</font>
</html:template>
Die vorgenommenen Änderungen sind:
  • div-Container um das Formular
  • Definition von Schrift-Art und -Größe
  • Jedes Formular-Element in einer eigenen Zeile
  • Ausgabe der Meldung oder des Ergebnisses wurde unterhalb des Buttons verschoben
Der Vollständigkeit halber hier nochmal der komplette Code der Controller-Datei:

Code: Alles auswählen

   class calc_controller extends baseController
   {

      function calc_controller(){
      }

      function transformContent(){

         // Formular-Objekt referenzieren
         $Form__CalcForm = &$this->__getForm('CalcForm');

         // Eingaben prüfen
         if($Form__CalcForm->get('isSent')){

            // Eingaben auslesen
            $Operand1 = &$Form__CalcForm->getFormElementByName('operand1');
            $Value1 = (int)$Operand1->getAttribute('value');
            $Operand2 = &$Form__CalcForm->getFormElementByName('operand2');
            $Value2 = (int)$Operand2->getAttribute('value');
            $Operator = &$Form__CalcForm->getFormElementByName('operation');
            $CurrentOperator = &$Operator->getSelectedOption();
            $OperaturType = $CurrentOperator->getAttribute('value');

            // Auf Division durch 0 prüfen
            if($OperaturType == 'dividieren' && intval($Value2) === 0){
               $Template__Error = &$this->__getTemplate('Error');
               $Form__CalcForm->setPlaceHolder('operand2error',$Template__Error->transformTemplate());
             // end if
            }
            else{

               // Ergebnis errechnen
               $Value1 = (int)$Operand1->getAttribute('value');
               $Value2 = (int)$Operand2->getAttribute('value');

               if($OperaturType == 'plus'){
                  $Result = $Value1 + $Value2;
                // end if
               }
               elseif($OperaturType == 'minus'){
                  $Result = $Value1 - $Value2;
                // end elseif
               }
               elseif($OperaturType == 'dividieren'){
                  $Result = $Value1 / $Value2;
                // end elseif
               }
               else{
                  $Result = $Value1 * $Value2;
                // end else
               }

               // Ergebnis darstellen
               $Template__Result = &$this->__getTemplate('Result');
               $Template__Result->setPlaceHolder('Result',$Result);
               $Form__CalcForm->setPlaceHolder('operand2error',$Template__Result->transformTemplate());

             // end else
            }

          // end if
         }

         // Formular darstellen
         $Form__CalcForm->transformOnPlace();

       // end function
      }

    // end class
   }
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 09.08.2008, 11:03:00

3.12. Schönheitskorrekturen im Controller
Wie dem spielerisch geneigten Leser aufgefallen sein dürfte, wird das Ergebnis bei jedem Klick auf den Button berechnet. Dies hat den Hintergrund, dass im Controller das Formular lediglich auf das Event isSent hin überprüft wird. Ausschlaggebend dafür ist die Kontrollstruktur

Code: Alles auswählen

if($Form__CalcForm->get('isSent')){
   ...
}
Ergänzen wird die Bedingung um die Prüfung auf das Event isValid, so wird das Ergebnis nur dann berechnet, wenn das Formular auch vollständig ausgefüllt ist. Die komplette Bedingung lautet dann

Code: Alles auswählen

if($Form__CalcForm->get('isSent') && $Form__CalcForm->get('isValid')){
   ...
}
Unser Modul ist nun zunächst fertig und bereit für den Einbau in eine fertige Seite.
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 10.08.2008, 22:37:12

3.13. Download und Installation der APF-Demo-Seite
Um das neu erstellte Modul in ein bestehendes Projekt integrieren zu können, brauchen wir zunächst eine bestehende Seite. Hierzu nutzen wir einfach die Demo-Webseite. Diese beinhaltet neben Hinweisen zu Online-Ressourcen und einigen Einsteiger-Tutorials auch eine Spielwiese.

Zunächst müssen wir die Beispiel-Seite jedoch lokal installieren. Hierzu laden wir das Package adventure-demopack-1.7-RC1-2008-08-09-1143-php5.zip für die PHP-Version 5 oder adventure-demopack-1.7-RC1-2008-08-09-1143-php4.zip für Version 4 herunter. Anschließend erstellen wir im DOCUMENT_ROOT des lokalen Webservers einen Ordner apfdemo und entpacken das Archiv dort. Der Aufruf der URL http://localhost/apfdemo/ sollte nun die Demo-Webseite zeigen.


3.14. Installation unseres Moduls in der Demo-Webseite
Da unser Modul bisher in einer anderen Code-Basis entwickelt wurde, müssen wir die relevanten Dateien in der Code-Basis des Demo-Projektes installieren. Dazu einfach den Ordner apf/apps/modules/calc/ nach apfdemo/apps/modules/ kopieren. Damit ist der Code des Moduls in der Beispielseite vorhanden und kann im nächsten Schritt eingebunden werden.


3.15. Einbindung des Moduls calc in die Spielwiese
Wurden die Ordner wie oben beschrieben angelegt, so ist die Spielwiesen-Seite unter http://localhost/apfdemo/de/?pagepart=spielwiese aufrufbar. Um das Modul einzubinden, müssen wir zunächst verstehen, wie die Seite aufgebaut ist, bzw. welche Templates manipuliert werden müssen. Dazu ziehen wir zunächst die Einfühung unter http://localhost/apfdemo/de/?pagepart=einfuehrung heran. Beim Durchlesen des Kapitel 1 fällt uns auf, dass alle Inhalte der Seite in Templates stecken. Diese sind unter apfdemo/apps/sites/apfexample/pres/templates/de/content/ abgelegt und heißen gleich den URL-Parametern beim Aufruf der Seite. Möchte ich also die Inhalte der Spielwiesenseite (URL: http://localhost/apfdemo/de/?pagepart=spielwiese) bearbeiten, muss das Template mit dem Namen spielwiese.html manipuliert werden. Die Inhalte der URL http://localhost/apfdemo/de/?pagepart=start können durch editieren der Datei start.html verändert werden. Für die Einbindung unseres Moduls nutzen wir also die Datei spielwiese.html.

Wie bereits am Anfang angesprochen, kann jede Template-Datei mit dem Tag

Code: Alles auswählen

<core:importdesign namespace="" template="" />
eingebunden werden. Dieses Tag nutzen wir auch für unser Modul. Da das Modul im Ordner (=Namespace) modules/calc/ und das einzubindende Template im Ordner pres/templates untergebracht ist, lautet der Inhalt des Attributs namespace modules::calc::pres::templates. Der Name des Templates ist gemäß TagLib-Definition der Name der Datei ohne Endung, sprich calc. Damit ergibt sich eine Tag-Definition von

Code: Alles auswählen

<core:importdesign namespace="modules::calc::pres::templates" template="calc" />
Kopieren wir diesen Quelltext in die oben genannte Datei, speichern diese und rufen die Spielweise-Seite erneut auf, wird unser Modul wie erwartet dargestellt und funktioniert ohne Änderungen.

Hier der Vollständigkeit nochmal der Inhalt des Templates spielwiese.html:

Code: Alles auswählen

<core:addtaglib namespace="sites::apfexample::pres::taglib" prefix="curr" class="date" />
<div style="text-align: right;">
  <em>Ausgabe des Tags <curr:date />:</em> <strong><curr:date /></strong>
</div>
<h3>Spielwiese</h3>
Diese Seite ist ein Platzhalter. Sie kann dazu genutzt werden um Erweiterungen und Modifikationen
auszuprobieren. Um diese Seite zu ver&auml;ndern, einfach die Datei
<pre class="tagexample">
apps/sites/apfexample/pres/templates/de/content/spielwiese.html
</pre>
ein einem Editor Ihrer Wahl &ouml;ffnen. Anregungen zum Ausprobieren finden sich im Tutorial
<a href="./?pagepart=tutorial" title="Erste Schritte">Erste Schritte</a>.
<br />
<br />
<br />
<br />
<core:importdesign namespace="modules::calc::pres::templates" template="calc" />
Damit ist unser calc-Modul erstellt und kann in beliebigen Seiten eingesetzt werden.


4. Ausblick
Aus Gründen der Einfachheit und um zu demonstrieren, wie einfach ein Modul erstellt werden kann, beinhaltet dieses keine Features wie
  • Mehrsprachigkeit
  • Konfigurierbares Layout
  • AJAX
Sofern Interesse besteht, können diese Features gerne noch an das Tutorial angehängt werden. Bei Interesse einfach den Thread mit eigenen Ideen erweitern.


5. Download
Zur Überprüfung deiner Arbeit kannst du folgende Demo-Pakete mit dem Modul calc herunterladen:
Dieses basieren auf der Version 1.7-RC1.


6. Feedback
Über Feedback zum Tutorial, Fragen oder Kommentare freue ich mich natürlich! :)
Viele Grüße,
Christian

Benutzeravatar
fliegermichl
Beiträge: 114
Registriert: 29.01.2008, 11:51:45
Wohnort: Echzell

Re: Minimales Modul

Beitrag von fliegermichl » 11.08.2008, 13:09:59

Hallo Doc,

Deine Antwortfrequenz ist wirklich beängstigend :-)
Ich habe Deine Postings bis zum Ende gelesen, Schritt für Schritt nachvollzogen, verstanden, das Patch mit dem Null Bug installiert und bin wieder mal etwas geplättet.
3.8.Erweiterung des Formulars
Das oben gezeigte Formular muss nun mit den gewünschten Operanden gefüllt werden. Dies kann im Controller oder direkt im Template erfolgen. Da die Operanden in diesem Beispiel der Einfachheit wegen statisch sind, spricht nichts gegen eine Definition im Template.
Das stimmt zwar, aber zu Lernzwecken wollte ich den Inhalt des Select Feldes trotzdem aus dem Controller heraus befüllen und verwende dazu folgenden Code:

Code: Alles auswählen

  $operations = &$Form__CalcForm->getFormElementByName('operations');
  // Hinzufügen der möglichen Operationen
  $operations->addOption('+', 'plus');
  $operations->addOption('-', 'minus');
  $operations->addOption('*', 'mal');
  $operations->addOption('/', 'durch');
Hier ist mir aufgefallen, dass mein ursprünglicher Template Eintrag name="operations[]" nicht funktionierte.
Ich bekam die Fehlermeldung, daß kein Formularelement "operations" existiert.
Frage: kann man die 4 addOption Aufrufe durch einen Aufruf ersetzen, dem gleich ein Array mit Werten übergeben wird?
Als nächstes ist Formular-Validierung und Plausibilitätsprüfung an der Reihe. Da das beim letzten Mal so gut geklappt hat, würde ich sagen: jetzt bist du dran! ;)
Das hätte ich sicher schon gemacht, währest Du mir nicht zuvorgekommen :-)

Wieso erzeugt ein $Form__CalcForm->setPlaceHolder('Ergebnis', $Ergebnis) eine Fehlermeldung, wenn im Template

Code: Alles auswählen

<form:placeholder name="Ergebnis" /> 
fehlt?

Von anderen Frameworks kenne ich, dass man Platzhalter verwenden kann aber nicht muß.

Ich habe in meinem Controller noch weitere Fehlermöglichkeiten berücksichtigt, nämlich, daß operand1 und operand2 Zahlen sein müssen.
Der Controller schaut nun so aus:

Code: Alles auswählen

 function transformContent() {
  $hasErrors = false;
  $Form__CalcForm = &$this->__getForm('CalcForm');
  $operations = &$Form__CalcForm->getFormElementByName('operations');

  // Hinzufügen der möglichen Operationen
  $operations->addOption('+', 'plus');
  $operations->addOption('-', 'minus');
  $operations->addOption('*', 'mal');
  $operations->addOption('/', 'durch');

  if ($Form__CalcForm->get('isSent'))
  {
    // Das Formular wurde durch den Benutzer abgeschickt, also validieren wir die Eingabewerte
    $wert1 = $Form__CalcForm->getFormElementByName('operand1')->getAttribute('value');
    if (!is_numeric($wert1)) {
     $Form__CalcForm->setPlaceHolder('operand1error', 'Bitte eine Zahl eingeben!');
     $hasErrors = true;
    }

    $wert2 = $Form__CalcForm->getFormElementByName('operand2')->getAttribute('value');
    if (!is_numeric($wert2)) {
     $Form__CalcForm->setPlaceHolder('operand2error', 'Bitte eine Zahl eingeben!');
     $hasErrors = true;
    }

    $operation = $Form__CalcForm->getFormElementByName('operations')->getSelectedOption()->getAttribute('value');
    if (($operation == 'durch') and ($wert2 === 0)) {
     $Form__CalcForm->setPlaceHolder('operand2error', 'Bitte nicht durch Null dividieren!');
     $hasErrors = true;
    }

    if (!$hasErrors) {
     if     ($operation == 'plus')  { $Ergebnis = $wert1 + $wert2; }
     elseif ($operation == 'minus') { $Ergebnis = $wert1 - $wert2; }
     elseif ($operation == 'mal')   { $Ergebnis = $wert1 * $wert2; }
     else                           { $Ergebnis = $wert1 / $wert2; }
     $Form__CalcForm->setPlaceHolder('Ergebnis', $Ergebnis);
    }
  }
  $Form__CalcForm->transformOnPlace();
 }
Das funktioniert schon ganz gut.
Allerdings werden die Eingabefelder rot markiert, wenn kein Fehler aufgetreten ist, umgekehrt werden diese nicht markiert wenn Fehler aufgetreten sind. Gibt es da eine implizite Automatik mit "formelementname" und "formelementnameerror"?

Das Thema Templates und Einbinden des Moduls in "Fremdseiten" schaue ich mir nun nochmal separat an.

Vielen Dank für Deine Geduld mit uns "normalsterblichen" :D

Viele Grüße
Michl

Benutzeravatar
fliegermichl
Beiträge: 114
Registriert: 29.01.2008, 11:51:45
Wohnort: Echzell

Re: Minimales Modul

Beitrag von fliegermichl » 11.08.2008, 14:11:33

Ich hab eben gesehen, daß es doch nicht so ist. Beim ersten Aufruf sind die Eingabefelder nicht markiert. Danach sind sie immer rot markiert, egal ob ein Fehler aufgetreten ist oder nicht.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 11.08.2008, 16:47:24

Hallo fliegermichl,

sorry, dass ich das Tutorial schon zu Ende geführt habe, ich wollte es jedoch mit dem 1.7-RC1 veröffentlichen. Ich denke es bietet jedoch noch einiges an Gesprächsbedarf. :)
Hier ist mir aufgefallen, dass mein ursprünglicher Template Eintrag name="operations[]" nicht funktionierte.
Ich bekam die Fehlermeldung, daß kein Formularelement "operations" existiert.
Richtig. An dieser Stelle habe ich das Template aus deinem Post geändert. Grund: es macht keinen Sinn ein Mehrfach-Auswahfeld für den Operanden auszuweisen, da mathematisch gesehen zu einer Zeit nur ein Operand Gültigkeit besitzt. Die eckigen Klammern sind auch nur dann von Nöten, wenn in einem Feld mehrere Optionen gleichzeitig selektierbar sein sollen. Das Template beinhaltete an dieser Stelle deshalb ein

Code: Alles auswählen

    <form:select name="operation">
      <select:option value="plus">+</select:option>
      <select:option value="minus">-</select:option>
      <select:option value="dividieren">/</select:option>
      <select:option value="multiplizieren">*</select:option>
    </form:select>
Im Controller kannst du dieses Feld damit per

Code: Alles auswählen

$Operator = &$Form__CalcForm->getFormElementByName('operation');
addressieren. Sorry, das ist im Text vielleicht etwas untergegangen...
Frage: kann man die 4 addOption Aufrufe durch einen Aufruf ersetzen, dem gleich ein Array mit Werten übergeben wird?
Nein, dies wird von den API-Funktionen nicht unterstützt. Denkbar wäre das natürlich schon, müsste aber implementiert werden. Sofern von deiner Seite Interesse besteht, kann ich das in die Feature-Liste der nächsten Version aufnehmen.
Wieso erzeugt ein $Form__CalcForm->setPlaceHolder('Ergebnis', $Ergebnis) eine Fehlermeldung, wenn im Template

Code: Alles auswählen

    <form:placeholder name="Ergebnis" />
fehlt?

Von anderen Frameworks kenne ich, dass man Platzhalter verwenden kann aber nicht muß.

Ich bin etwas verwirrt, denn ich finde die Definitionsstelle des von dir genannten Codes nicht. Wo ist diese Zeile enthalten? Grundsätzlich hast du natürlich Recht, es können nur Platzhalter verwendet werden, die auch definiert sind. Andernfalls wirst du mit einer entsprechenden Fehlermeldung darauf aufmerksam gemacht.
Das funktioniert schon ganz gut.
Allerdings werden die Eingabefelder rot markiert, wenn kein Fehler aufgetreten ist, umgekehrt werden diese nicht markiert wenn Fehler aufgetreten sind. Gibt es da eine implizite Automatik mit "formelementname" und "formelementnameerror"?
Kannst du mir bitte den Inhalt deines templates posten, damit ich das verhalten lokal nachstellen kann? Danke!
Vielen Dank für Deine Geduld mit uns "normalsterblichen" :D
Nicht doch. Ich finde die Diskussion äußerst spannend!
Viele Grüße,
Christian

Benutzeravatar
fliegermichl
Beiträge: 114
Registriert: 29.01.2008, 11:51:45
Wohnort: Echzell

Re: Minimales Modul

Beitrag von fliegermichl » 12.08.2008, 09:29:56

Guten Morgen Doc,
Ich bin etwas verwirrt, denn ich finde die Definitionsstelle des von dir genannten Codes nicht. Wo ist diese Zeile enthalten? Grundsätzlich hast du natürlich Recht, es können nur Platzhalter verwendet werden, die auch definiert sind. Andernfalls wirst du mit einer entsprechenden Fehlermeldung darauf aufmerksam gemacht.
Naja, der Code Designer stellt zu einem Objekt eine Reihe von verfügbaren Platzhaltern zur Verfügung und der Template Bauer nimmt diejenigen, welche er in seinem aktuellen Template gerade braucht.

Beispielsweise ein Basket Object.

Dieses kann 20 Positionen oder mehr enthalten. Der Template Bauer sagt sich aber.
"Ach nö, hier bastel ich nur so eine kleine View, welche oben rechts in der Ecke stehen soll. Da zeige ich nur die ersten 3 Positionen und dann einen Link "mehr ..." und zeige unten die Gesamtsumme aller im Warenkorb liegenden Positionen."

Klickt der Anwender den Link an, zeige ich (gleiches Objekt, anderes Template) alle Positionen an.
Auch werden in dem einen Template nicht alle Platzhalter gebraucht, im nächsten zwar vielleicht auch nicht alle aber eben andere als im ersten usw.

Aber ich will nicht nörgeln. Das kleine Beispiel mit dem Rechner ist wirklich ein guter Einstieg.

hier nochmal mein letztes Template (wegen der roten Feldumrandungen)

Code: Alles auswählen

<@controller namespace="modules::calc::pres::documentcontroller" file="calc_controller" class="calc_controller" @>
<core:addtaglib namespace="tools::form::taglib" prefix="html" class="form" />
<html:form name="CalcForm" method="post" action="">
    <form:placeholder name="operand1error" />
    Operand1: <form:text name="operand1" class="eingabe_feld" validate="true" button="docalc" />
    Operation: <form:select name="operations" />
    <form:placeholder name="operand2error" />
    Operand2: <form:text name="operand2" class="eingabe_feld" validate="true" button="docalc" />
    <br />
    <form:button name="docalc" value="Berechnen" />
    <br />
    Ergebnis: <form:placeholder name="Ergebnis" />
</html:form>
Ich melde mich, falls noch Fragen auftauchen sollten.
Vielen Dank für Deine Unterstützung

Gruß
Michl

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 12.08.2008, 13:32:06

Hallo fliegermichl,
Naja, der Code Designer stellt zu einem Objekt eine Reihe von verfügbaren Platzhaltern zur Verfügung und der Template Bauer nimmt diejenigen, welche er in seinem aktuellen Template gerade braucht.
Ach jetzt verstehe ich, was du meinst. Du hast einen HTML-/XML-Editor, der dem Template-Entwickler ein Satz an Tags zur Verfügung stellt, den der Template-Entwickler verwenden kann. Da die Platzhalter-Tags (<html:placeholder />) jedoch mehrdeutig sind, haben diese ein Attribut name, mit dem sie eindeutig innerhalb des aktuellen Templates vom Controller referenzierbar sind. Das bedeutet natürlich, dass eine Änderung des Tags eine Änderung im Controller nach sich zieht, da der Controller eine gültige Referenz auf den Platzhalter benötigt. Scheint zunächst zwar umständlich, die Bindung zwischen Controller und Template ist im Sinne des MVC-Pattern jedoch relativ fest.
"Ach nö, hier bastel ich nur so eine kleine View, welche oben rechts in der Ecke stehen soll. Da zeige ich nur die ersten 3 Positionen und dann einen Link "mehr ..." und zeige unten die Gesamtsumme aller im Warenkorb liegenden Positionen."

Klickt der Anwender den Link an, zeige ich (gleiches Objekt, anderes Template) alle Positionen an.
Auch werden in dem einen Template nicht alle Platzhalter gebraucht, im nächsten zwar vielleicht auch nicht alle aber eben andere als im ersten usw.
Diese Funktionalität würde man anders umsetzen. In unserem einfachen Beispiel kommen wir ohne das M im MVC-Pattern aus, für das von dir beschriebene Verhalten benötigen wir jedoch ein Model, das die Informationen über die aktuelle Darstellung beinhaltet. Konkreter Lösungsansatz ist, dass in einem Template je nach Model-Informationen die zwei genannten Views (Übersicht und Detail-Ansicht) darstellt werden. Die beiden Views haben dabei jeweils ein eigenes Template und einen eigenen Controller, nutzen jedoch die Informationen des Models und einer Business-Schicht, die an Hand der Model-Informationen als Datenquelle genutzt werden kann.

Ich kann auch hier gerne noch ein Beispiel erstellen, mit dem klar wird, wie die Implementierung konkret funktioniert. Als Literaturstellen kann ich schon mal folgende nennen:
Aber ich will nicht nörgeln. Das kleine Beispiel mit dem Rechner ist wirklich ein guter Einstieg.
Danke!
hier nochmal mein letztes Template (wegen der roten Feldumrandungen)
Danke, ich verde das heute Abend prüfen, ich habe gerade keine Entwicklungsumgebung zur Hand.
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4555
Registriert: 04.11.2007, 16:13:53

Re: Minimales Modul

Beitrag von dr.e. » 13.08.2008, 21:11:06

Hallo fliegermichl,

bin gestern Abend nicht mehr dazu gekommen, dein Template anzusehen und hab das jetzt nachgeholt. Die Felder werden - wie bei den Formular-TagLibs üblich bei Absenden des Formulars validiert. Ist die Eingabe nicht korrekt, wird ein Textfeld rot umrandet. Möchtest du lediglich die Ausgabe der Hinweistexte haben, darf die Validierung des einzelnen Text-Feldes nicht aktiviert werden. In diesem Fall muss in der Template-Datei statt

Code: Alles auswählen

  Operand1: <form:text name="operand1" class="eingabe_feld" validate="true" button="docalc" />
nur

Code: Alles auswählen

  Operand1: <form:text name="operand1" class="eingabe_feld" />
stehen. Die Validierung könnte man an dieser Stelle auch noch etwas eleganter lösen, in dem du die Validierungsmethode validateNumber() der Klasse myValidator verwendest. Möchtest du einen Hinweistext ausgeben, kannst du das <form:genericval /> verwenden. Statt der Controller-Anweisung

Code: Alles auswählen

        $wert1 = $Form__CalcForm->getFormElementByName('operand1')->getAttribute('value');
        if (!is_numeric($wert1)) {
         $Form__CalcForm->setPlaceHolder('operand1error', 'Bitte eine Zahl eingeben!');
         $hasErrors = true;
        }
könntest du auch im Template ein

Code: Alles auswählen

<form:genericval field="operand1" button="docalc" validator="Number">Bitte eine Zahl eingeben!</form:genericval>
an geeigneter Stelle einfügen.Grundsätzlich lässt sich damit die im Controller implementierte Validierung komplett über das Template regeln.

Ich hoffe, das beantwortet deine Fragen. :)
Viele Grüße,
Christian

Benutzeravatar
fliegermichl
Beiträge: 114
Registriert: 29.01.2008, 11:51:45
Wohnort: Echzell

Re: Minimales Modul

Beitrag von fliegermichl » 15.08.2008, 12:53:53

Hallo Doc,

Hmm, wenn ich die <form:placeholder> aus dem Template durch <form:genericval> ersetze, werden die Eingabefelder nicht mehr rot. Aber auch dann nicht, wenn der Anwender was falsches eingegeben hat.

Kann ich innerhalb von transformContent auf die Fehlertexte zugreifen um z.B. die Fehlermeldung anzupassen wenn
der Anwender versucht durch Null zu teilen?

Der Validator "Number" läßt nur die Eingabe ganzer positiver Zahlen zu. Gibt es auch einen für reale Zahlen?

Gruß
Michl

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast