Multiplier: componente dinamice

Instrument pentru crearea dinamică a componentelor interactive

Să pornim de la un exemplu tipic: avem o listă de produse într-un magazin online, iar pentru fiecare dorim să afișăm un formular pentru adăugarea produsului în coș. Una dintre variantele posibile este să încapsulăm întreaga listă într-un singur formular. O modalitate mult mai convenabilă ne oferă însă Nette\Application\UI\Multiplier.

Multiplier permite definirea convenabilă a unei fabrici pentru mai multe componente. Funcționează pe principiul componentelor imbricate – fiecare componentă care moștenește de la Nette\ComponentModel\Container poate conține alte componente.

Vezi capitolul despre modelul de componente în documentație sau prezentarea lui Honza Tvrdík.

Esența Multiplierului este că acționează în poziția de părinte, care își poate crea descendenții dinamic folosind un callback transmis în constructor. Vezi exemplul:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function () {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('count', 'Număr produse:')
			->setRequired();
		$form->addSubmit('send', 'Adaugă în coș');
		return $form;
	});
}

Acum putem, în șablon, să lăsăm pur și simplu să se redea formularul pentru fiecare produs – și fiecare va fi într-adevăr o componentă unică.

{foreach $items as $item}
	<h2>{$item->title}</h2>
	{$item->description}

	{control "shopForm-$item->id"}
{/foreach}

Argumentul transmis în tag-ul {control} este în formatul care spune:

  1. obține componenta shopForm
  2. și din ea obține descendentul $item->id

La prima apelare a punctului 1. shopForm încă nu există, așa că se apelează fabrica sa createComponentShopForm. Pe componenta obținută (instanța Multiplierului) este apoi apelată fabrica formularului specific – care este funcția anonimă pe care am transmis-o Multiplierului în constructor.

În următoarea iterație a foreach-ului, metoda createComponentShopForm nu va mai fi apelată (componenta există), dar deoarece căutăm un alt descendent al său ($item->id va fi diferit în fiecare iterație), funcția anonimă va fi apelată din nou și ne va returna un nou formular.

Singurul lucru care rămâne de făcut este să ne asigurăm că formularul ne adaugă în coș într-adevăr produsul pe care trebuie – în prezent, formularul este complet identic pentru fiecare produs. Ne ajută proprietatea Multiplierului (și, în general, a fiecărei fabrici de componente din Nette Framework), și anume că fiecare fabrică primește ca prim argument numele componentei create. În cazul nostru, acesta va fi $item->id, care este exact informația de care avem nevoie. Este suficient, așadar, să modificăm ușor crearea formularului:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function ($itemId) {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('count', 'Număr produse:')
			->setRequired();
		$form->addHidden('itemId', $itemId);
		$form->addSubmit('send', 'Adaugă în coș');
		return $form;
	});
}
versiune: 4.0