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:

  1. szerezd meg a shopForm komponenst
  2. é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;
	});
}
verzió: 4.0