Personnaliser le code HTML d’un widget symfony
Comme dit le proverbe, billet du mardi, billet symfony… Bon on va dire que c’est un nouveau proverbe mais pour le coup, on va continuer cet adage avec au programme aujourd’hui les possibilités offertes par symfony pour modifier le code HTML construit par ses fameux widgets de son système de formulaire.
Plus mon nombre de projets défile sous Symfony et plus j’essaye d’éviter de faire des choses hors framework, mais plutôt de voir comment on pourrait le régler via le framework. Avant, quand un problème se présentait, j’optais souvent pour une solution alternative quitte à mettre de côté pour une petite fonction la philosophie Symfony. Mais voilà, je l’aime moi, cette philosophie et au fur et à mesure, j’ai décidé de mettre de plus en plus les mains dans la cambouis et les yeux dans le code source, pour résoudre mes problèmes.
Récemment, j’étais sur un petit système de sondage très basique qui se présentait donc sous cette forme grâce au complément sfWidgetFormChoice et sfWidgetFormSelectCheckbox:

Grâce à un code du genre:
$this->widgetSchema['reponses'] = new sfWidgetFormChoice(array( 'multiple' => true, 'expanded' => true, 'choices' => $reponses ));
qui me produisait quelque chose comme ça:
<ul class="radio_list"> <li><input type="checkbox" id="etude_question_2_reponses_7" value="7" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_7">Oula</label></li> <li><input type="checkbox" id="etude_question_2_reponses_8" value="8" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_8">Ola</label></li> <li><input type="checkbox" id="etude_question_2_reponses_9" value="9" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_9">Woot</label></li> <li><input type="checkbox" id="etude_question_2_reponses_10" value="10" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_10">Wagli</label></li> <li><input type="checkbox" id="etude_question_2_reponses_11" value="11" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_11">Plop</label></li> </ul>
Ca fonctionne parfaitement, mais voilà à l’intégration, j’avais 2 checkbox par ligne… Et pour réaliser ça, j’avais besoin de modifier le code HTML que Symfony m’avait gentiment généré.
Et donc là, je me suis lancé dans une session de formatting grâce au sfFormatter. En effet, Symfony intègre en règle générale un code HTML par défaut, pour un peu tout, mais nous laisse parfaitement la possibilité de le modifier. Ici, je veux juste pouvoir rajouter une class CSS différente pour les éléments pair et impair. On va donc réécrire la fonction de formatting du widget comme ceci:
$this->widgetSchema['reponses'] = new sfWidgetFormChoice(array( 'multiple' => true, 'expanded' => true, 'choices' => $reponses, 'renderer_options' => array('formatter' => array($this, 'formatter')) // Ici on passe l'option formatter avec comme valeur la fonction formatter que l'on va ajouter à notre formulaire ));
Puis maintenant, on ajoute la fameuse fonction. J’ai choisi ici de la laisser dans mon formulaire, on peut très bien la mettre où on veut:
public function formatter($widget, $inputs) { $rows = array(); foreach ($inputs as $i => $input) { $rows[] = $widget->renderContentTag( 'li', $input['input'].$widget->getOption('label_separator').$input['label'], ($i%2>0?array('class' => 'pair'):array('class' => 'impair')) //Seule réelle modification par rapport à la fonction définie de base dans la classe sfWidgetFormSelectCheckbox ); } return $widget->renderContentTag('ul', implode($widget->getOption('separator'), $rows), array('class' => 'radio_list')); }
Et voilà mon code HTML ressemble maintenant à:
<ul class="radio_list"> <li class="impair"><input type="checkbox" id="etude_question_2_reponses_7" value="7" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_7">Oula</label></li> <li class="pair"><input type="checkbox" id="etude_question_2_reponses_8" value="8" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_8">Ola</label></li> <li class="impair"><input type="checkbox" id="etude_question_2_reponses_9" value="9" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_9">Woot</label></li> <li class="pair"><input type="checkbox" id="etude_question_2_reponses_10" value="10" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_10">Wagli</label></li> <li class="impair"><input type="checkbox" id="etude_question_2_reponses_11" value="11" name="etude[question_2][reponses][]"/> <label for="etude_question_2_reponses_11">Plop</label></li> </ul>
Je peux maintenant appliquer mon CSS pour faire la modification demandée à l’origine! Cette astuce fonctionne pour tous les widgets qui embarque du html autre que le simple tag input.
Tags: astuce, form, formatter, Symfony
8 Réponses
Laisser un message

Toujours sympa les astuces de ce style !
Merci à toi et à bientôt !
Content que ca puisse servir ;)
sinon pour personnaliser les checkbox html il y a ça ***
C’est la fête tiens. Ton lien n’avait aucun lien avec le sujet du billet.
salut,
k’ai un probleme avec sfWidgetFormPropelSelectMany
ce widget me permet de selectionner les elements ke je veux en appuyant sur (Ctrl), et moi je veux que ça soit un chekbox ou un autre tag sans utiliser le (Ctrl)
je souhaite trouver ma reponse ici
Bonjour shakir,
Il te suffit de rajouter l’option expanded à true dans la définition de ton widget comme dans l’exemple. Adapté à tes besoins, ça donnerait ceci:
Oh pourquoi je vois ce blog que maintenant ?
Je me suis fatigué à écrire un decorateur et un formatter alors que la solution était bien plus simple…
T’es trop foooort Tim !! ça va, je t’ai bien formé… lol