Multiplicator: Componente dinamice

Un instrument pentru crearea dinamică de componente interactive

Să începem cu o problemă tipică: avem o listă de produse pe un site de comerț electronic și dorim să însoțim fiecare produs cu un formular add to cart. O modalitate este de a îngloba întreaga listă într-un singur formular. O modalitate mai convenabilă este să folosim Nette\Application\UI\Multiplier.

Multiplicatorul vă permite să definiți o fabrică pentru mai multe componente. Se bazează pe principiul componentelor imbricate – fiecare componentă care moștenește din Nette\ComponentModel\Container poate conține alte componente.

Consultați modelul de componente în documentație.

Multiplier se prezintă ca o componentă părinte care își poate crea în mod dinamic copiii folosind callback-ul transmis în constructor. A se vedea exemplul:

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;
	});
}

În șablon putem reda un formular pentru fiecare produs – și fiecare formular 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 la eticheta {control} spune:

  1. obține o componentă shopForm
  2. și returnează copilul său $item->id

În timpul primului apel al 1., componenta shopForm nu există încă, astfel încât metoda createComponentShopForm este apelată pentru a o crea. O funcție anonimă transmisă ca parametru la Multiplicator, este apoi apelată și se creează un formular.

În iterațiile ulterioare ale foreach, metoda createComponentShopForm nu mai este apelată deoarece componenta există deja. Dar, deoarece facem referire la un alt copil ($item->id variază între iterații), este apelată din nou o funcție anonimă și este creat un nou formular.

Ultimul lucru este să ne asigurăm că formularul adaugă efectiv produsul corect în coș, deoarece în starea actuală toate formularele sunt egale și nu putem distinge căror produse aparțin. Pentru aceasta putem folosi proprietatea Multiplicator (și în general a oricărei metode de fabrică de componente din Nette Framework) ca fiecare metodă de fabrică de componente să primească ca prim argument numele componentei create. În cazul nostru, acesta ar fi $item->id, care este exact ceea ce avem nevoie pentru a distinge produsele individuale. Tot ce trebuie să faceți este să modificați codul de creare a formularului:

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;
	});
}
versiune: 4.0