Multiplier: dinamične komponente
Orodje za dinamično ustvarjanje interaktivnih komponent
Izhajajmo iz tipičnega primera: imejmo seznam blaga v spletni trgovini, pri čemer bomo pri vsakem želeli izpisati obrazec za dodajanje blaga v košarico. Ena od možnih variant je oviti celoten izpis v en obrazec. Veliko udobnejši način pa nam ponuja Nette\Application\UI\Multiplier.
Multiplier omogoča udobno definiranje tovarniške metode za več komponent. Deluje na principu ugnezdenih komponent – vsaka komponenta, ki deduje od Nette\ComponentModel\Container, lahko vsebuje druge komponente.
Glej poglavje o komponentnem modelu v dokumentaciji ali predavanje Honze Tvrdíka.
Bistvo Multiplierja je, da nastopa v vlogi starša, ki si svoje potomce lahko ustvarja dinamično s pomočjo povratnega klica (callback), predanega v konstruktorju. Glej primer:
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function () {
$form = new Nette\Application\UI\Form;
$form->addInteger('count', 'Število kosov:')
->setRequired();
$form->addSubmit('send', 'Dodaj v košarico');
return $form;
});
}
Zdaj lahko v predlogi enostavno pri vsakem blagu pustimo izrisati obrazec – in vsak bo resnično edinstvena komponenta.
{foreach $items as $item}
<h2>{$item->title}</h2>
{$item->description}
{control "shopForm-$item->id"}
{/foreach}
Argument, predan v znački {control}
, je v formatu, ki pravi:
- pridobi komponento
shopForm
- in iz nje pridobi potomca
$item->id
Pri prvem klicu točke 1. shopForm
še ne obstaja, zato se pokliče njegova tovarna
createComponentShopForm
. Na pridobljeni komponenti (instanci Multiplierja) je nato poklicana tovarna konkretnega
obrazca – kar je anonimna funkcija, ki smo jo Multiplierju v konstruktorju predali.
V naslednji iteraciji foreacha metoda createComponentShopForm
ne bo več klicana (komponenta obstaja), ker pa
iščemo njenega drugega potomca ($item->id
bo v vsaki iteraciji drugačen), bo ponovno poklicana anonimna
funkcija in nam vrnila nov obrazec.
Edino, kar preostane, je zagotoviti, da nam obrazec v košarico doda resnično tisto blago, ki ga mora – trenutno je
obrazec pri vsakem blagu popolnoma enak. Pomagala nam bo lastnost Multiplierja (in na splošno vsake tovarne na komponento
v Nette Frameworku), in sicer ta, da vsaka tovarna kot svoj prvi argument dobi ime tvořené komponenty. V našem primeru bo to
$item->id
, kar je točno tisti podatek, ki ga potrebujemo. Dovolj je torej rahlo prilagoditi tvorbu obrazca:
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function ($itemId) {
$form = new Nette\Application\UI\Form;
$form->addInteger('count', 'Število kosov:')
->setRequired();
$form->addHidden('itemId', $itemId);
$form->addSubmit('send', 'Dodaj v košarico');
return $form;
});
}