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:

  1. egy komponens kinyerése shopForm
  2. é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;
	});
}
verzió: 4.0