Zend_Form : configurer les decorators pour retirer les dt et les dd

Les decorators Zend_Form

Vous n'aimez pas le trio de balises dl/dt/dd que Zend_Form utilise pour envelopper ses champs ? Pas de problème, on peut les remplacer par une bonne vieille balise table.

Si vous n'êtes pas familier avec les decorators, je vous recommande la lecture de mon précédent article sur le sujet.

Prenons un formulaire d'identification classique :

class Votreapp_Form_Login extends Zend_Form
{
    public function init()
    {
        $this->addElement(
            'text',
            'username',
            array(
                'label' => 'Nom d\'utilisateur :'
            )
        );
        $this->addElement(
            'password',
            'password',
            array(
                'label' => 'Mot de passe :'
            )
        );
        $this->addElement(
            'submit',
            'submit',
            array(
                'label' => 'OK'
            )
        );
    }
}

Sans CSS, ce formulaire est rendu de la façon suivante :

Le rendu du formulaire d'identification avec les balises dt/dd

Le code HTML :

<form enctype="application/x-www-form-urlencoded" action="" method="post">
    <dl class="zend_form">
        <dt id="username-label">
            <label for="username" class="optional">Nom d'utilisateur :</label>
        </dt>
        <dd id="username-element">
            <input type="text" name="username" id="username" value="">
        </dd>
        <dt id="password-label">
            <label for="password" class="optional">Mot de passe :</label>
        </dt>
        <dd id="password-element">
            <input type="password" name="password" id="password" value="">
        </dd>
        <dt id="submit-label">&nbsp;</dt><dd id="submit-element">
            <input type="submit" name="submit" id="submit" value="OK">
        </dd>
    </dl>
</form>

Pour transformer tout ça en tableau, on va d'abord commencer par envelopper les champs par des balises td et les étiquettes par des balises th. Le tout sera entouré par une balise tr :

$decorators = array(
    'ViewHelper',
    'Errors',
    array('Description', array('tag' => 'p', 'class' => 'description')),
    array('HtmlTag', array('tag' => 'td')),
    array('Label', array('tag' => 'th')),
    array(array('tr' => 'HtmlTag'), array('tag' => 'tr'))
);
$this->addElement(
    'text',
    'username',
    array(
        'decorators' => $decorators,
        'label' => 'Nom d\'utilisateur :'
    )
);
$this->addElement(
    'password',
    'password',
    array(
        'decorators' => $decorators,
        'label' => 'Mot de passe :'
    )
);

On utilise deux fois le décorateur HtmlTag. On doit donc lui donner un alias avec array('tr' => 'HtmlTag').

Pour le bouton submit, c'est un peu différent. On n'a pas besoin de Errors et de Description et on doit appliquer un attribut colspan pour fusionner les deux cellules du tableau :

$this->addElement(
    'submit',
    'submit',
    array(
        'decorators' => array(
            'ViewHelper',
            array(array('td' => 'HtmlTag'), array('tag' => 'td', 'colspan' => 2)),
            array(array('tr' => 'HtmlTag'), array('tag' => 'tr'))
        ),
        'label' => 'OK'
    )
);

Pour finir, on remplace la balise dl du formulaire par une balise table.

$this->setDecorators(
    array(
        'FormElements',
        array('HtmlTag', array('tag' => 'table')),
        'Form'
    )
);

On obtient le rendu suivant :

Le rendu du formulaire d'identification avec les balises table/tr/th/td

Le code HTML :

<form enctype="application/x-www-form-urlencoded" action="" method="post">
    <table>
        <tr>
            <th id="username-label">
                <label for="username" class="optional">Nom d'utilisateur :</label>
            </th>
            <td>
                <input type="text" name="username" id="username" value="">
            </td>
        </tr>
        <tr>
            <th id="password-label">
                <label for="password" class="optional">Mot de passe :</label>
            </th>
            <td>
                <input type="password" name="password" id="password" value="">
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" name="submit" id="submit" value="OK">
            </td>
        </tr>
    </table>
</form>
Portrait de Anonyme

Naan, c'est mieux les dd : on

Naan, c'est mieux les dd : on peut plus facilement avec qu'avec les tables.
Bon exemple néanmoins pour jouer avec le display des formulaires.

Portrait de Maxence Delannoy

Le problème du trio dl/dt/dd,

Le problème du trio dl/dt/dd, c'est qu'on doit systématiquement avoir un dt avec le dd. Ce qui fait que pour ajouter un fieldset à un formulaire, on doit l'envelopper d'un dd et ajouter un dt vide devant pour que ce soit valide au niveau HTML (le décorateur DtDdWrapper est d'ailleurs fait pour ça). Sinon on s'expose à ce genre de bogue.

Ils auraient du utiliser des simples balises div.

Portrait de Anonyme

euh, ce sujet aurait du

euh, ce sujet aurait du s'appeler " comment transformer les decorateurs dd/dt/dl de zend en table " et non comment les virer .....
Sinon, savez vous comment on les vires tout simplement ?

Portrait de Maxence Delannoy

Pour ceux qui n'aiment pas

Pour ceux qui n'aiment pas les décorateurs, il y a un moyen très simple de s'en passer. Il suffit d'utiliser les méthodes render* qui permettent d'effectuer le rendu de chaque décorateur séparément. Exemple :

// On suppose qu'on a un formulaire avec un champ texte nommé name
 
// On supprime la balise DT du décorateur Label
$this->form->name->getDecorator('label')->setOption('tag', null);
 
// Le code suivant affiche uniquement la balise LABEL
echo $this->form->name->renderLabel();
 
// Le code suivant affiche uniquement la balise INPUT
echo $this->form->name->renderViewHelper();

De cette façon, on a autant de souplesse que si on codait le formulaire en HTML et on bénéficie de toute la puissance de Zend_Form.

Pour plus de détail, il faut consulter cet article (en anglais) du grand gourou Matthew Weier O'Phinney.

Portrait de Anonyme

j'ai suivi ton tutoriel mais

j'ai suivi ton tutoriel mais j'ai une message d'erreur:
Exception caught by form: Plugin by name 'Array' was not found in the registry; used paths: Zend_Form_Decorator_: Zend/Form/Decorator/ Stack Trace: #0 D:\projet\projet1\library\Zend\Form\Element.php(1717): .....

voici ce comment j'ai procéder:
$element->addDecorator("$decorators");
si vous avez une idée s'il vous plait?

Portrait de Anonyme

Merci pour ton tutoriel, pour

Merci pour ton tutoriel, pour mon souci fallait faire:
$element->addDecorators("$decorators");

Portrait de Anonyme

comment faire pour un fichier

comment faire pour un fichier j'ai un souci le décorateur m'affiche deux fois :

Portrait de Anonyme

désolé voici le code: input

désolé voici le code:
input type="file" name="Image" id="Image">

Portrait de Anonyme

Bonjour, Très bien cette

Bonjour,
Très bien cette explication mais comment peut-on faire pour personnaliser les multicheckbox ? J'aimerais afficher 30 checkbox en 5 lignes de 6 mais impossible de trouver quelque part sur internet la solution à mon problème car la multicheckbox affiche mes 30 checkbox en liste. Et si j'enlève les séparateurs (setSeparator('')) il me les affiche toutes à la suite...
Quelqu'un aurait-il une solution ?
Merci

Portrait de Maxence Delannoy

Je pense que tu dois écrire

Je pense que tu dois écrire un ViewHelper personnalisé.

Poster un nouveau commentaire

Le contenu de ce champ ne sera pas montré publiquement. If you have a Gravatar account, used to display your avatar.
  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Les lignes et les paragraphes vont à la ligne automatiquement.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. The supported tag styles are: <foo>, [foo].

Plus d'informations sur les options de formatage

CAPTCHA
La vérification ne tient pas compte des minuscules ou des majuscules.
Image CAPTCHA
Enter the characters shown in the image.