veilletech.fr
4 nov. Feed du jour
#06 SYMFONY Article

Symfony 8.2 : collections de formulaires polymorphes

Une ligne se reconnaît à son identité, pas à sa place.

Symfony 8.2 ajoute PolymorphicCollectionType, qui permet à une collection de formulaires de mélanger plusieurs types d'entrées, et l'option entry_name, qui identifie chaque ligne par ses données plutôt que par sa position. Cela règle le cas où l'ordre change entre l'affichage et l'envoi. Attention : avec allow_add, un nouveau nom identique à celui d'une entrée existante met cette entrée à jour.

2 min de lectureintermédiairevidéo 1:20
Partager
Sommaire5 sections
  1. Ce qui se passe
  2. Des entrées de types différents
  3. Des lignes nommées d'après leurs données
  4. Le piège à éviter
  5. À retenir

Ce qui se passe

CollectionType est le champ standard pour éditer une liste d'éléments dans un formulaire Symfony. Il traîne deux limites : toutes ses entrées partagent le même type de formulaire, et les lignes envoyées sont rattachées aux entrées par leur position. Symfony 8.2 lève les deux, avec deux contributions du billet « New in Symfony 8.2 ».

Des entrées de types différents

Pour une page de CMS faite de blocs (titre, paragraphe, pied de page), une seule option entry_type ne suffit plus. Le nouveau PolymorphicCollectionType (Michael Käfer, PR #63487) déclare un type de formulaire par sorte d'entrée, plus un fournisseur qui choisit le bon type pour chaque entrée, via l'option entry_type_provider.

Le fournisseur reçoit les données d'une entrée sous deux formes, d'où deux méthodes. L'une, forSubmittedData(), ne sert que pour les lignes ajoutées dans le navigateur : leurs données envoyées ne contiennent que les valeurs des champs, donc chaque type d'entrée y ajoute un champ caché et non mappé type qui porte le nom de l'entrée.

Avec allow_add, Symfony produit un prototype par type d'entrée, exposé dans des attributs HTML data-prototype-<nom> (data-prototype-heading, data-prototype-paragraph…) que votre JavaScript choisit d'insérer. Les options entry_options, prototype_options et prototype_data fonctionnent comme dans CollectionType, mais leurs valeurs sont indexées par nom d'entrée.

Des lignes nommées d'après leurs données

Les sous-formulaires d'une collection portent le nom des clés de ses entrées. Si l'ordre change entre le rendu et l'envoi (un autre utilisateur a modifié les mêmes données, par exemple), les valeurs de la ligne 0 sont écrites dans l'entrée qui occupe maintenant la clé 0.

La nouvelle option entry_name (Nicolas Grekas), disponible sur CollectionType comme sur PolymorphicCollectionType, nomme chaque formulaire d'après l'entrée elle-même. Sa valeur peut être un chemin de propriété lu sur chaque entrée, ou un callable qui reçoit l'entrée et sa clé, utile quand certaines entrées n'ont pas encore d'identifiant. Le tag d'identifiant 42 stocké à la clé 0 donne alors des champs post[tags][42][name] au lieu de post[tags][0][name], mais les valeurs vont toujours à ce tag et la collection garde ses clés d'origine.

Le piège à éviter

Avec allow_add, une nouvelle ligne dont le nom correspond à une entrée existante met cette entrée à jour. Un compteur numérique peut tomber sur l'identifiant d'une entrée : nommez les nouvelles lignes avec des noms qu'aucune entrée ne peut avoir, comme new_1.

Source : blog Symfony, en anglais. Les exemples de code complets y figurent.