Nette Documentation Preview

syntax
Multiplier: dynamische Komponenten
**********************************
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Multiplier: dynamische Komponenten

Werkzeug zur dynamischen Erstellung interaktiver Komponenten

Beginnen wir mit einem typischen Beispiel: Wir haben eine Liste von Waren in einem E-Shop, und für jede Ware möchten wir ein Formular zum Hinzufügen in den Warenkorb anzeigen. Eine mögliche Variante ist, die gesamte Auflistung in ein einziges Formular zu packen. Einen viel bequemeren Weg bietet uns jedoch Nette\Application\UI\Multiplier.

Multiplier ermöglicht es, bequem eine Factory für mehrere Komponenten zu definieren. Es funktioniert nach dem Prinzip verschachtelter Komponenten – jede Komponente, die von Nette\ComponentModel\Container erbt, kann weitere Komponenten enthalten.

Siehe das Kapitel über das Komponentenmodell in der Dokumentation oder den Vortrag von Honza Tvrdík.

Das Wesen des Multipliers ist, dass er als Elternteil fungiert, der seine Nachkommen dynamisch mithilfe eines im Konstruktor übergebenen Callbacks erstellen kann. Siehe Beispiel:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function () {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('count', 'Anzahl der Artikel:') // 'Počet zboží:' -> 'Anzahl der Artikel:'
			->setRequired();
		$form->addSubmit('send', 'In den Warenkorb legen'); // 'Přidat do košíku' -> 'In den Warenkorb legen'
		return $form;
	});
}

Jetzt können wir im Template einfach für jeden Artikel das Formular rendern lassen – und jedes wird tatsächlich eine eindeutige Komponente sein.

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

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

Das im Tag {control} übergebene Argument hat ein Format, das besagt:

  1. hole die Komponente shopForm
  2. und hole daraus den Nachkommen $item->id

Beim ersten Aufruf von Punkt 1. existiert shopForm noch nicht, also wird seine Factory createComponentShopForm aufgerufen. Auf der erhaltenen Komponente (Instanz des Multipliers) wird dann die Factory des konkreten Formulars aufgerufen – was die anonyme Funktion ist, die wir dem Multiplier im Konstruktor übergeben haben.

In der nächsten Iteration des Foreach wird die Methode createComponentShopForm nicht mehr aufgerufen (die Komponente existiert), aber da wir einen anderen Nachkommen suchen ($item->id wird in jeder Iteration anders sein), wird die anonyme Funktion erneut aufgerufen und gibt uns ein neues Formular zurück.

Das Einzige, was übrig bleibt, ist sicherzustellen, dass das Formular tatsächlich die richtige Ware in den Warenkorb legt – derzeit ist das Formular für jeden Artikel völlig identisch. Hier hilft uns eine Eigenschaft des Multipliers (und generell jeder Komponenten-Factory im Nette Framework), nämlich dass jede Factory als erstes Argument den Namen der zu erstellenden Komponente erhält. In unserem Fall ist das $item->id, was genau die Information ist, die wir benötigen. Es genügt also, die Erstellung des Formulars leicht anzupassen:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function ($itemId) {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('count', 'Anzahl der Artikel:') // 'Počet zboží:' -> 'Anzahl der Artikel:'
			->setRequired();
		$form->addHidden('itemId', $itemId);
		$form->addSubmit('send', 'In den Warenkorb legen'); // 'Přidat do košíku' -> 'In den Warenkorb legen'
		return $form;
	});
}