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 :

<?php
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 :

<?php
$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 :

<?php
$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.

<?php
$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>

Commentaires

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.

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.

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 ?

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.

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?

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

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

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

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

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

Pages

Ajouter un commentaire