Multiplier : composants dynamiques
Outil pour la création dynamique de composants interactifs
Partons d'un exemple typique : nous avons une liste de produits dans une boutique en ligne, et pour chacun, nous voulons afficher un formulaire pour ajouter le produit au panier. Une possibilité est d'englober toute la liste dans un seul formulaire. Cependant, Nette\Application\UI\Multiplier nous offre une manière beaucoup plus pratique.
Multiplier permet de définir facilement une petite factory pour plusieurs composants. Il fonctionne sur le principe des composants imbriqués – chaque composant héritant de Nette\ComponentModel\Container peut contenir d'autres composants.
Voir le chapitre sur le modèle de composant dans la documentation ou la présentation de Honza Tvrdík.
L'essence de Multiplier est qu'il agit en tant que parent capable de créer dynamiquement ses enfants à l'aide d'un callback passé dans le constructeur. Voir l'exemple :
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function () {
$form = new Nette\Application\UI\Form;
$form->addInteger('count', 'Nombre de produits :')
->setRequired();
$form->addSubmit('send', 'Ajouter au panier');
return $form;
});
}
Maintenant, nous pouvons simplement faire afficher le formulaire pour chaque produit dans le template – et chacun sera réellement un composant unique.
{foreach $items as $item}
<h2>{$item->title}</h2>
{$item->description}
{control "shopForm-$item->id"}
{/foreach}
L'argument passé dans la balise {control}
est dans un format qui dit :
- obtenir le composant
shopForm
- et à partir de celui-ci, obtenir l'enfant
$item->id
Lors du premier appel du point 1., shopForm
n'existe pas encore, donc sa factory
createComponentShopForm
est appelée. Sur le composant obtenu (instance de Multiplier), la factory du formulaire
spécifique est ensuite appelée – c'est la fonction anonyme que nous avons passée à Multiplier dans le constructeur.
Dans l'itération suivante de foreach, la méthode createComponentShopForm
ne sera plus appelée (le composant
existe), mais comme nous recherchons un autre de ses enfants ($item->id
sera différent à chaque itération), la
fonction anonyme sera à nouveau appelée et nous retournera un nouveau formulaire.
La seule chose qui reste à faire est de s'assurer que le formulaire ajoute réellement au panier le produit qu'il doit
ajouter – actuellement, le formulaire est exactement le même pour chaque produit. La propriété de Multiplier (et en
général de chaque factory de composant dans Nette Framework) nous aide, à savoir que chaque factory reçoit comme premier
argument le nom du composant créé. Dans notre cas, ce sera $item->id
, ce qui est exactement l'information dont
nous avons besoin. Il suffit donc de modifier légèrement la création du formulaire :
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function ($itemId) {
$form = new Nette\Application\UI\Form;
$form->addInteger('count', 'Nombre de produits :')
->setRequired();
$form->addHidden('itemId', $itemId);
$form->addSubmit('send', 'Ajouter au panier');
return $form;
});
}