Multiplier: componenti dinamici
Strumento per la creazione dinamica di componenti interattivi
Partiamo da un esempio tipico: abbiamo un elenco di prodotti in un e-shop, e per ognuno vogliamo visualizzare un form per aggiungere il prodotto al carrello. Una delle possibili varianti è racchiudere l'intero elenco in un unico form. Tuttavia, un modo molto più comodo ci viene offerto da Nette\Application\UI\Multiplier.
Multiplier consente di definire comodamente una piccola factory per più componenti. Funziona sul principio dei componenti nidificati – ogni componente che eredita da Nette\ComponentModel\Container può contenere altri componenti.
Vedi il capitolo sul modello a componenti nella documentazione o la presentazione di Honza Tvrdík.
L'essenza di Multiplier è che agisce come genitore, che può creare dinamicamente i propri figli tramite un callback passato nel costruttore. Vedi l'esempio:
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function () {
$form = new Nette\Application\UI\Form;
$form->addInteger('count', 'Quantità:')
->setRequired();
$form->addSubmit('send', 'Aggiungi al carrello');
return $form;
});
}
Ora possiamo semplicemente far renderizzare un form per ogni prodotto nel template – e ognuno sarà effettivamente un componente unico.
{foreach $items as $item}
<h2>{$item->title}</h2>
{$item->description}
{control "shopForm-$item->id"}
{/foreach}
L'argomento passato nel tag {control}
è nel formato che dice:
- ottieni il componente
shopForm
- e da esso ottieni il figlio
$item->id
Alla prima chiamata del punto 1. shopForm
non esiste ancora, quindi viene chiamata la sua factory
createComponentShopForm
. Sul componente ottenuto (istanza di Multiplier) viene poi chiamata la factory del form
specifico – che è la funzione anonima che abbiamo passato a Multiplier nel costruttore.
Nella successiva iterazione del foreach, il metodo createComponentShopForm
non verrà più chiamato (il componente
esiste), ma poiché stiamo cercando un suo figlio diverso ($item->id
sarà diverso in ogni iterazione), la
funzione anonima verrà chiamata di nuovo e ci restituirà un nuovo form.
L'unica cosa che resta da fare è assicurarsi che il form aggiunga al carrello effettivamente il prodotto che deve –
attualmente il form è completamente identico per ogni prodotto. Ci aiuta una proprietà di Multiplier (e in generale di ogni
factory di componente in Nette Framework), ovvero che ogni factory riceve come primo argomento il nome del componente creato. Nel
nostro caso sarà $item->id
, che è esattamente l'informazione di cui abbiamo bisogno. Basta quindi modificare
leggermente la creazione del form:
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function ($itemId) {
$form = new Nette\Application\UI\Form;
$form->addInteger('count', 'Quantità:')
->setRequired();
$form->addHidden('itemId', $itemId);
$form->addSubmit('send', 'Aggiungi al carrello');
return $form;
});
}