Szorzó: Dinamikus összetevők
Interaktív komponensek dinamikus létrehozásának eszköze
Kezdjük egy tipikus problémával: van egy terméklistánk egy e-kereskedelmi oldalon, és minden termékhez szeretnénk egy add to cart űrlapot mellékelni. Az egyik lehetőség, hogy az egész listát egyetlen űrlapba csomagoljuk. Kényelmesebb megoldás a Nette\Application\UI\Multiplier.
A Multiplier lehetővé teszi, hogy több komponenshez gyárat definiáljunk. Ez az egymásba ágyazott komponensek elvén alapul – minden egyes komponens, amely a Nette\ComponentModel\Container -tól örököl, tartalmazhat más komponenseket.
Lásd a dokumentációban a komponensmodellt.
A Multiplier olyan szülő komponensként pózol, amely dinamikusan létrehozhatja gyermekeit a konstruktorban átadott visszahívás segítségével. Lásd a példát:
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function () {
$form = new Nette\Application\UI\Form;
$form->addInteger('amount', 'Amount:')
->setRequired();
$form->addSubmit('send', 'Add to cart');
return $form;
});
}
A sablonban minden termékhez egy űrlapot tudunk renderelni – és minden űrlap valóban egyedi komponens lesz.
{foreach $items as $item}
<h2>{$item->title}</h2>
{$item->description}
{control "shopForm-$item->id"}
{/foreach}
A {control}
tagnek átadott argumentum szerint:
- egy komponens kinyerése
shopForm
- és adja vissza a gyermekét
$item->id
Az 1. első hívása során a shopForm
komponens még nem létezik, ezért a
createComponentShopForm
metódust hívjuk meg a létrehozásához. Ezután egy névtelen függvényt hívunk meg,
amelyet paraméterként átadunk a Multiplier-nek, és létrehozunk egy űrlapot.
A foreach
további iterációiban a createComponentShopForm
metódus már nem hívódik meg, mivel a
komponens már létezik. Mivel azonban egy másik gyermekre hivatkozunk ($item->id
változik az iterációk
között), ismét meghívódik egy névtelen függvény, és létrejön egy új űrlap.
Az utolsó dolog, hogy biztosítsuk, hogy az űrlap valóban a megfelelő terméket adja hozzá a kosárhoz, mert a jelenlegi
állapotban minden űrlap egyforma, és nem tudjuk megkülönböztetni, hogy melyik termékhez tartoznak. Ehhez használhatjuk a
Multiplier (és általában a Nette Frameworkben minden komponensgyári metódusnak) azt a tulajdonságát, hogy minden
komponensgyári metódus első argumentumként megkapja a létrehozott komponens nevét. A mi esetünkben ez a
$item->id
, amire pontosan szükségünk van az egyes termékek megkülönböztetéséhez. Mindössze annyit kell
tennünk, hogy módosítjuk az űrlap létrehozására szolgáló kódot:
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function ($itemId) {
$form = new Nette\Application\UI\Form;
$form->addInteger('amount', 'Amount:')
->setRequired();
$form->addHidden('itemId', $itemId);
$form->addSubmit('send', 'Add to cart');
return $form;
});
}