<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: no -->
<sect1 id="learning.form.decorators.individual">
    <title>Darstellung individueller Decorators</title>

    <para>
        Im <link linkend="learning.form.decorators.layering">vorigen Abschnitt</link> haben wir uns
        angesehen wie man Decorators kombinieren kann um komplexe Ausgaben zu erstellen. Wir haben
        gesehen dass, obwohl wir eine Tonne an Flexibilität mit diesem Ansatz haben, fügt er auch
        einiges an Komplexität und Overhead hinzu. In diesem Abschnitt behandeln wir wie Decorators
        individuell dargestellt werden können um eigene Markups für Formulare und/oder individuelle
        Elemente zu erstellen.
    </para>

    <para>
        Sobald man die Decorators registriert hat, kann man Sie später durch Ihren Namen vom Element
        erhalten. Sehen wir uns das vorhergehende Beispiel nochmals an:
    </para>

    <programlisting language="php"><![CDATA[
$element = new Zend_Form_Element('foo', array(
    'label'      => 'Foo',
    'belongsTo'  => 'bar',
    'value'      => 'test',
    'prefixPath' => array('decorator' => array(
        'My_Decorator' => 'path/to/decorators/',
    )),
    'decorators' => array(
        'SimpleInput'
        array('SimpleLabel', array('placement' => 'append')),
    ),
));
]]></programlisting>

    <para>
        Wenn wir nur den <classname>SimpleInput</classname> holen und darstellen wollen, können wir
        das tun indem wir die Methode <methodname>getDecorator()</methodname> verwenden:
    </para>

    <programlisting language="php"><![CDATA[
$decorator = $element->getDecorator('SimpleInput');
echo $decorator->render('');
]]></programlisting>

    <para>
        Das ist recht einfach kann aber sogar noch einfacher gemacht werden; machen wir es in einer
        einzelnen Zeile:
    </para>

    <programlisting language="php"><![CDATA[
echo $element->getDecorator('SimpleInput')->render('');
]]></programlisting>

    <para>
        Nicht schlecht, aber trotzdem noch etwas komplex. Um es noch einfacher zu machen wurde mit
        1.7 eine Kurzschreibweise in <classname>Zend_Form</classname> eingeführt: man kann jeden
        registrierten Decorator darstellen indem eine Methode des Formats
        <methodname>renderDecoratorName()</methodname> aufgerufen wird. Das wird effektiv
        ausgeführt wie man oben sieht, macht aber das <varname>$content</varname> Argument optional
        und vereinfacht die Verwendung:
    </para>

    <programlisting language="php"><![CDATA[
echo $element->renderSimpleInput();
]]></programlisting>

    <para>
        Das ist ein netter Trick, aber wie und warum sollte man Ihn verwenden?
    </para>

    <para>
        Viele Entwickler und Designer haben sehr präzise Notwendigkeiten für das Markup in Ihren
        Formularen. Sie würden eher volle Kontrolle über Ihre Ausgabe haben wollen als auf eine
        automatisiertere Lösung zu stützen welche mit Ihrem Design mehr oder weniger konform geht.
        In anderen Fällen benötigt das Layout des Formulars ein spezialisierteres Markup --
        gruppieren von eigenen Elementen, einige von Ihnen unsichtbar solange bis ein bestimmter
        Link ausgewählt wurde, usw.
    </para>

    <para>
        Sehen wir uns die Fähigkeit an individuelle Decorators darzustellen und ein
        spezialisierteres Markup zu erstellen.
    </para>

    <para>
        Definieren wir als erstes ein Formular. Unser Formular holt demografische Details des
        Benutzers. Das Markup wird sehr stark anpassbar sein, und in einigen Fällen View Helfer
        direkt verwenden statt den Formular Elementen um seine Ziele zu erreichen. Hier ist die
        grundsätzliche Definition des Formulars:
    </para>

    <programlisting language="php"><![CDATA[
class My_Form_UserDemographics extends Zend_Form
{
    public function init()
    {
        // Einen Pfad für eigene Decorators hinzufügen
        $this->addElementPrefixPaths(array(
            'decorator' => array('My_Decorator' => 'My/Decorator'),
        ));

        $this->addElement('text', 'firstName', array(
            'label' => 'Vorname: ',
        ));
        $this->addElement('text', 'lastName', array(
            'label' => 'Nachname: ',
        ));
        $this->addElement('text', 'title', array(
            'label' => 'Titel: ',
        ));
        $this->addElement('text', 'dateOfBirth', array(
            'label' => 'Geburtsdatum (DD/MM/YYYY): ',
        ));
        $this->addElement('text', 'email', array(
            'label' => 'Emailadresse: ',
        ));
        $this->addElement('password', 'password', array(
            'label' => 'Passwort: ',
        ));
        $this->addElement('password', 'passwordConfirmation', array(
            'label' => 'Passwort wiederholen: ',
        ));
    }
}
]]></programlisting>

    <note>
        <para>
            Wir definieren jetzt keine Prüfungen oder Filter, da Sie für die Diskussion der
            Decorators nicht relevant sind. In einem Real-World Szenario sollte man Sie definieren.
        </para>
    </note>

    <para>
        Da dass auf dem Weg ist, besprechen wir wie dieses Formular angezeigt werden soll. Eine
        übliche Ausdrucksweise mit Vor-/Nachnamen ist Sie in einer einzelnen Zeile anzuzeigen;
        wenn ein Titel angegeben wird, ist er oft auch in der selben Zeile. Daten werden oft in
        drei Felder separiert und Seite an Seite angezeigt, wen keine JavaScript Datumsauswahl
        verwendet wird.
    </para>

    <para>
        Verwenden wir die Fähigkeit die Decorators eines Elements einzeln darzustellen um das zu
        ermöglichen. Erstens ist zu beachten das keine expliziten Decorators für die angegebenen
        Elemente definiert wurden. Als Auffrischung sind die standardmäßigen Decorators für die
        (meisten) Elemente:
    </para>

    <itemizedlist>
        <listitem>
            <para>
                <classname>ViewHelper</classname>: Verwendet einen View Helfer um eine
                Formulareingabe darzustellen
            </para>
        </listitem>

        <listitem>
            <para>
                <classname>Errors</classname>: Verwendet den View Helfer
                <classname>FormErrors</classname> um Prüfungsfehler darzustellen
            </para>
        </listitem>

        <listitem>
            <para>
                <classname>Description</classname>: Verwendet den View Helfer
                <classname>FormNote</classname> um die Beschreibung des Elements darzustellen
                (wenn vorhanden)
            </para>
        </listitem>

        <listitem>
            <para>
                <classname>HtmlTag</classname>: Umschließt die obigen drei Elemente mit einem
                <emphasis>&lt;dd&gt;</emphasis> Tag
            </para>
        </listitem>

        <listitem>
            <para>
                <classname>Label</classname>: Stellt die Überschrift des Elements dar indem es den
                View Helfer <classname>FormLabel</classname> verwendet (und Ihn in ein
                <emphasis>&lt;dt&gt;</emphasis> Tag umhüllt)
            </para>
        </listitem>
    </itemizedlist>

    <para>
        Auch als Auffrischung, kann man auf jedes Element eines Formulars zugreifen wie wenn es die
        Eigenschaft einer Klasse wäre; auf das Element muss einfach mit dem Namen verwiesen werden
        der Ihm zugeordnet wurde.
    </para>

    <para>
        Unser View Skript könnte dann wie folgt aussehen:
    </para>

    <programlisting language="php"><![CDATA[
<?php
$form = $this->form;
// Entfernt <dt> von der Erstellung der Überschrift
foreach ($form->getElements() as $element) {
    $element->getDecorator('label')->setOption('tag', null);
}
?>
<?php echo $form->renderForm(false); ?>
    <div class="element">
        <?php echo $form->title->renderLabel()
              . $form->title->renderViewHelper() ?>
        <?php echo $form->firstName->renderLabel()
              . $form->firstName->renderViewHelper() ?>
        <?php echo $form->lastName->renderLabel()
              . $form->lastName->renderViewHelper() ?>
    </div>
    <div class="element">
        <?php echo $form->dateOfBirth->renderLabel() ?>
        <?php echo $this->formText('dateOfBirth[day]', '', array(
            'size' => 2, 'maxlength' => 2)) ?>
        /
        <?php echo $this->formText('dateOfBirth[month]', '', array(
            'size' => 2, 'maxlength' => 2)) ?>
        /
        <?php echo $this->formText('dateOfBirth[year]', '', array(
            'size' => 4, 'maxlength' => 4)) ?>
    </div>
    <div class="element">
        <?php echo $form->password->renderLabel()
              . $form->password->renderViewHelper() ?>
    </div>
    <div class="element">
        <?php echo $form->passwordConfirmation->renderLabel()
              . $form->passwordConfirmation->renderViewHelper() ?>
    </div>
    <?php echo $this->formSubmit('submit', 'Speichern') ?>
</form>
]]></programlisting>

    <para>
        Wenn man obiges View Skript verwendet erhält man voraussichtlich das folgende
        <acronym>HTML</acronym> (angenähert da das <acronym>HTML</acronym> von anbei formatiert
        ist):
    </para>

    <programlisting language="html"><![CDATA[
<form method="post" action="">
    <div class="element">
        <label for="title" tag="" class="optional">Titel:</label>
        <input type="text" name="title" id="title" value=""/>

        <label for="firstName" tag="" class="optional">Vorname:</label>
        <input type="text" name="firstName" id="firstName" value=""/>

        <label for="lastName" tag="" class="optional">Nachname:</label>
        <input type="text" name="lastName" id="lastName" value=""/>
    </div>

    <div class="element">
        <label for="dateOfBirth" tag="" class="optional">Geburtsdatum
            (DD/MM/YYYY):</label>
        <input type="text" name="dateOfBirth[day]" id="dateOfBirth-day"
            value="" size="2" maxlength="2"/>
        /
        <input type="text" name="dateOfBirth[month]" id="dateOfBirth-month"
            value="" size="2" maxlength="2"/>
        /
        <input type="text" name="dateOfBirth[year]" id="dateOfBirth-year"
            value="" size="4" maxlength="4"/>
    </div>

    <div class="element">
        <label for="password" tag="" class="optional">Passwort:</label>
        <input type="password" name="password" id="password" value=""/>
    </div>

    <div class="element">
        <label for="passwordConfirmation" tag="" class="" id="submit"
            value="Speichern"/>
</form>
]]></programlisting>

    <para>
        Ist mag nicht wirklich schön sein, aber mit etwas CSS könnte man es so verändern das es
        exakt so aussieht wie man es haben will. Der Punkt ist, das dieses Formular erstellt wurde
        indem fast komplett eigenes Markup verwendet wurde, wärend trotzdem Decorators für das
        meiste gemeinsame Markup verwendet wurden (und um sicherzustellen das Dinge wie das Escaping
        mit HtmlEntities und die Injektion von Werten stattfinden).
    </para>

    <para>
        Ab diesem Punkt des Tutorials sollte man sich recht gut auskennen not den Möglichkeiten
        des Markups wenn <classname>Zend_Form</classname>'s Decorators verwendet werden. Im nächsten
        Abschnitt sehen wir uns das Datumselement von oben nochmals an, und demonstrieren wie ein
        eigenes Element und ein Decorator für kombinierte Elemente erstellt werden kann.
    </para>
</sect1>
