Multiplier: dinamikus komponensek
Eszköz interaktív komponensek dinamikus létrehozásához
Induljunk ki egy tipikus példából: van egy terméklistánk egy webáruházban, és mindegyiknél szeretnénk kiírni egy űrlapot a termék kosárba helyezéséhez. Az egyik lehetséges változat az egész listát egyetlen űrlapba csomagolni. Sokkal kényelmesebb módszert kínál azonban a Nette\Application\UI\Multiplier.
A Multiplier lehetővé teszi több komponenshez tartozó factory kényelmes definiálását. Az beágyazott komponensek elvén működik – minden Nette\ComponentModel\Container-től öröklődő komponens tartalmazhat további komponenseket.
Lásd a komponens modellről szóló fejezetet a dokumentációban vagy Honza Tvrdík előadását.
A Multiplier lényege, hogy szülőként lép fel, aki a leszármazottait dinamikusan tudja létrehozni a konstruktorban átadott callback 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('count', 'Termékek száma:')
->setRequired();
$form->addSubmit('send', 'Kosárba');
return $form;
});
}
Most a sablonban egyszerűen minden terméknél megjeleníthetjük az űrlapot – és mindegyik valóban egyedi komponens lesz.
{foreach $items as $item}
<h2>{$item->title}</h2>
{$item->description}
{control "shopForm-$item->id"}
{/foreach}
A {control}
tagben átadott argumentum formátuma a következőt mondja:
- szerezd meg a
shopForm
komponenst - és abból szerezd meg a
$item->id
leszármazottat
Az 1. pont első hívásakor a shopForm
még nem létezik, ezért meghívódik a
createComponentShopForm
factory-ja. A megszerzett komponensen (a Multiplier példányán) ezután meghívódik a
konkrét űrlap factory-ja – ami az az anonim függvény, amelyet a Multipliernek a konstruktorban átadtunk.
A foreach következő iterációjában a createComponentShopForm
metódus már nem hívódik meg (a komponens
létezik), de mivel egy másik leszármazottját keressük ($item->id
minden iterációban más lesz), újra
meghívódik az anonim függvény, és visszaad nekünk egy új űrlapot.
Az egyetlen dolog, ami hátra van, az annak biztosítása, hogy az űrlap valóban azt a terméket adja hozzá a kosárhoz,
amelyet kell – jelenleg az űrlap minden terméknél teljesen azonos. Ebben segít a Multiplier (és általában minden
komponens factory a Nette Frameworkben) tulajdonsága, mégpedig az, hogy minden factory első argumentumként megkapja a
létrehozott komponens nevét. Esetünkben ez $item->id
lesz, ami pontosan az az adat, amire szükségünk van.
Tehát csak kissé módosítani kell az űrlap létrehozását:
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function ($itemId) {
$form = new Nette\Application\UI\Form;
$form->addInteger('count', 'Termékek száma:')
->setRequired();
$form->addHidden('itemId', $itemId);
$form->addSubmit('send', 'Kosárba');
return $form;
});
}