<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 24249 -->
<!-- Reviewed: no -->
<sect1 id="learning.form.decorators.individual">
    <title>Rendu individuel des décorateurs</title>

    <para>
        Dans la <link linkend="learning.form.decorators.layering">section précédente</link>, nous
        avons vu comment combiner les décorateurs afin de créer un rendu complexe. Ceci est très fléxible
        mais rajoute tout de même un part de compléxité à l'ensemble. Dans ce chapitre, nous allons
        inspecter le rendu individuel des décorateurs afin de créer du contenu visuel pour des
        formulaires ou des éléments.
    </para>

    <para>
        Une fois des décorateurs enregistrés, vous pouvez les récupérer via leur nom depuis l'élément.
        Revoyons l'exemple précédent:
    </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>
        Si nous voulons récupérer le décorateur <classname>SimpleInput</classname>, nous passons
        par la méthode <methodname>getDecorator()</methodname>:
    </para>

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

    <para>
        C'est simple et ça peut l'être encore plus; ré-écrivons le tout sur une seule ligne:
    </para>

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

    <para>
        Pas mauvais, mais toujours un peu compliqué. Pour simplifier, une notation raccourcie a été
        introduite dans <classname>Zend_Form</classname> en 1.7: vous pouvez rendre n'importe quel
        décorateur enregistré en appelant une méthode de la forme
        <methodname>renderDecoratorName()</methodname>.
        Ceci effectue le rendu et fait en sorte que <varname>$content</varname> soit optionnel ce qui
        simplifie l'utilisation:
    </para>

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

    <para>
        C'est une simplification astucieuse, mais comment et pourquoi l'utiliser?
    </para>

    <para>
        Beaucoup de développeurs ont des besoins très précis en affichage des formulaires. Ils préfèrent
        avoir un contrôle complet sur tout l'affichage plutôt que d'utiliser une solution automatisée
        qui peut s'écarter de leur but initial. Dans d'autres cas, les formulaires peuvent demander
        un affichage extrêmement spécifique, en groupant des éléments alors que d'autres doivent
        pouvoir être invisibles avant que l'on n'effectue telle action sur la page, etc.
    </para>

    <para>
        Utilisons la possibilité de rendre un seul décorateur pour créer un affichage précis.
    </para>

    <para>
        D'abord, définissons un formulaire. Celui-ci récupèrera des détails démographiques sur l'utilisateur.
        Le rendu sera hautement personnalisé et dans certains cas il utilisera les aides de vue directement
        plutôt que les éléments. Voici une définition simple du formulaire:
    </para>

    <programlisting language="php"><![CDATA[
class My_Form_UserDemographics extends Zend_Form
{
    public function init()
    {
        // Ajoute un chemin pour les décorateurs personnalisés
        $this->addElementPrefixPaths(array(
            'decorator' => array('My_Decorator' => 'My/Decorator'),
        ));

        $this->addElement('text', 'firstName', array(
            'label' => 'First name: ',
        ));
        $this->addElement('text', 'lastName', array(
            'label' => 'Last name: ',
        ));
        $this->addElement('text', 'title', array(
            'label' => 'Title: ',
        ));
        $this->addElement('text', 'dateOfBirth', array(
            'label' => 'Date of Birth (DD/MM/YYYY): ',
        ));
        $this->addElement('text', 'email', array(
            'label' => 'Your email address: ',
        ));
        $this->addElement('password', 'password', array(
            'label' => 'Password: ',
        ));
        $this->addElement('password', 'passwordConfirmation', array(
            'label' => 'Confirm Password: ',
        ));
    }
}
]]></programlisting>

    <note>
        <para>
            Nous n'utilisons pas de validateurs ou de filtres ici, car ils n'ont rien à voir avec le
            rendu visuel qui nous interesse. En réalité, il y en aurait.
        </para>
    </note>

    <para>
        Maintenant réfléchissons au rendu visuel du formulaire. Une communalité concernant les nom
        et prénom est qu'on les affiche l'un à coté de l'autre, à coté de leur titre, si présent.
        Les dates, si elles n'utilisent pas Javascript, affichent souvent des champs séparés pour
        chaque segment de la date.
    </para>

    <para>
        Utilisons la possibilité de rendre des décorateurs un par un pour accomplir notre tâche.
        D'abord, notez qu'aucun décorateur spécifique n'a été renseigné dans les éléments.
        Rappelons donc les décorateurs par défaut de la plupart des éléments:
    </para>

    <itemizedlist>
        <listitem>
            <para>
                <classname>ViewHelper</classname>: utilise une aide de vue pour rendre l'élément
                balise de formulaire à proprement parlé.
            </para>
        </listitem>

        <listitem>
            <para>
                <classname>Errors</classname>: utilise l'aide de vue <classname>FormErrors</classname>
                pour afficher les erreurs de validation éventuelles.
            </para>
        </listitem>

        <listitem>
            <para>
                <classname>Description</classname>: utilise l'aide de vue <classname>FormNote</classname>
                afin de rendre la description éventuelle de l'élément.
            </para>
        </listitem>

        <listitem>
            <para>
                <classname>HtmlTag</classname>: encapsule les trois objets ci-dessus dans un tag
                <emphasis>&lt;dd&gt;</emphasis>.
            </para>
        </listitem>

        <listitem>
            <para>
                <classname>Label</classname>: rend l'intitulé de l'élément en utilisant l'aide de vue
                <classname>FormLabel</classname> (et en encapsulant le tout dans un tag
                <emphasis>&lt;dt&gt;</emphasis>).
            </para>
        </listitem>
    </itemizedlist>

    <para>
        Nous vous rappelons aussi que vous pouvez accéder à tout élément individuellement en tant
        qu'attribut du formulaire représentant son nom.
    </para>

    <para>
        Notre script de vue ressemblerait à cela:
    </para>

    <programlisting language="php"><![CDATA[
<?php
$form = $this->form;
// Enlève le <dt> depuis l'intitulé
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', 'Save') ?>
</form>
]]></programlisting>

    <para>
        Si vous utilisez le script ci-dessus, vous verrez un code HTML ressemblant à ceci:
    </para>

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

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

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

    <div class="element">
        <label for="dateOfBirth" tag="" class="optional">Date of Birth
            (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">Password:</label>
        <input type="password" name="password" id="password" value=""/>
    </div>

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

    <para>
        Ca peut ne pas ressembler à quelque chose de terminé, mais avec un peu de CSS, cela peut
        ressembler exactement à ce que vous cherchez. Le point important ici, c'est que le formulaire
        a été généré en utilisant de la décoration manuelle personnalisée (ainsi que l'utilisation
        d'échappement avec htmlentities).
    </para>

    <para>
        Grâce à cette partie du tutoriel, vous devriez être à l'aise avec les possibilité de rendu de
        <classname>Zend_Form</classname>. Dans la section suivante, nous verrons comment monter un
        élément de date grâce à des éléments et des décorateur uniques assemblés main.
    </para>
</sect1>
