Nette Documentation Preview

syntax
Multiplier: dynamische Komponenten
**********************************

.[perex]
Ein Werkzeug für die dynamische Erstellung interaktiver Komponenten.

Beginnen wir mit einem typischen Beispiel: Stellen Sie sich eine Produktliste in einem E-Shop vor, bei der Sie zu jedem Artikel ein Formular "In den Warenkorb legen" ausgeben möchten. Eine mögliche Variante ist, die gesamte Auflistung in ein einziges Formular zu packen. Einen viel bequemeren Weg bietet jedoch [api:Nette\Application\UI\Multiplier].

Der Multiplier erlaubt es, bequem eine Factory für mehrere Komponenten zu definieren. Er funktioniert nach dem Prinzip verschachtelter Komponenten - jede Komponente, die von [api:Nette\ComponentModel\Container] erbt, kann weitere Komponenten enthalten.

.[tip]
Siehe das Kapitel über das [Komponentenmodell |components#Komponenten im Detail] in der Dokumentation.

Das Wesen des Multipliers ist, dass er als Elternteil auftritt, der seine Kinder mithilfe eines im Konstruktor übergebenen Callbacks dynamisch erzeugen kann. Siehe das Beispiel:

```php
protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function () {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('amount', 'Anzahl:')
			->setRequired();
		$form->addSubmit('send', 'In den Warenkorb');
		return $form;
	});
}
```

Nun können wir im Template ganz einfach zu jedem Produkt das Formular ausgeben lassen - und jedes davon wird wirklich eine eigenständige Komponente sein.

```latte
{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 bedeutet:

1. Hole die Komponente `shopForm`.
2. Hole aus ihr das Kind mit dem Namen `$item->id`.

Beim ersten Aufruf von Punkt **1** existiert die Komponente `shopForm` noch nicht, daher wird ihre Factory `createComponentShopForm` aufgerufen. Auf der so erhaltenen Komponente (einer Instanz des Multipliers) wird dann die Factory des konkreten Formulars aufgerufen - das ist die anonyme Funktion, die wir dem Konstruktor des Multipliers übergeben haben.

In der nächsten Iteration der foreach-Schleife wird die Methode `createComponentShopForm` nicht erneut aufgerufen (die Komponente existiert bereits). Da wir jedoch ein anderes Kind suchen (denn `$item->id` ist in jeder Iteration anders), wird die anonyme Funktion erneut aufgerufen und liefert ein neues Formular zurück.

Es bleibt nur noch sicherzustellen, dass das Formular auch wirklich das richtige Produkt in den Warenkorb legt - derzeit ist das Formular bei jedem Produkt identisch. Dabei hilft uns eine Eigenschaft des Multipliers (und generell jeder Komponenten-Factory im Nette Framework): Jede Factory erhält als erstes Argument den Namen der erzeugten Komponente. Die Factory des Multipliers erhält darüber hinaus als zweites Argument die Instanz des Multipliers selbst. In unserem Fall ist das erste Argument `$item->id`, also genau die Information, die wir brauchen. Es genügt daher, die Erstellung des Formulars leicht anzupassen:

```php
protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function (string $itemId) {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('amount', 'Anzahl:')
			->setRequired();
		$form->addHidden('itemId', $itemId);
		$form->addSubmit('send', 'In den Warenkorb');
		return $form;
	});
}
```

Multiplier: dynamische Komponenten

Ein Werkzeug für die dynamische Erstellung interaktiver Komponenten.

Beginnen wir mit einem typischen Beispiel: Stellen Sie sich eine Produktliste in einem E-Shop vor, bei der Sie zu jedem Artikel ein Formular „In den Warenkorb legen“ ausgeben möchten. Eine mögliche Variante ist, die gesamte Auflistung in ein einziges Formular zu packen. Einen viel bequemeren Weg bietet jedoch Nette\Application\UI\Multiplier.

Der Multiplier erlaubt es, bequem eine Factory für mehrere Komponenten zu definieren. Er 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.

Das Wesen des Multipliers ist, dass er als Elternteil auftritt, der seine Kinder mithilfe eines im Konstruktor übergebenen Callbacks dynamisch erzeugen kann. Siehe das Beispiel:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function () {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('amount', 'Anzahl:')
			->setRequired();
		$form->addSubmit('send', 'In den Warenkorb');
		return $form;
	});
}

Nun können wir im Template ganz einfach zu jedem Produkt das Formular ausgeben lassen – und jedes davon wird wirklich eine eigenständige 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 bedeutet:

  1. Hole die Komponente shopForm.
  2. Hole aus ihr das Kind mit dem Namen $item->id.

Beim ersten Aufruf von Punkt 1 existiert die Komponente shopForm noch nicht, daher wird ihre Factory createComponentShopForm aufgerufen. Auf der so erhaltenen Komponente (einer Instanz des Multipliers) wird dann die Factory des konkreten Formulars aufgerufen – das ist die anonyme Funktion, die wir dem Konstruktor des Multipliers übergeben haben.

In der nächsten Iteration der foreach-Schleife wird die Methode createComponentShopForm nicht erneut aufgerufen (die Komponente existiert bereits). Da wir jedoch ein anderes Kind suchen (denn $item->id ist in jeder Iteration anders), wird die anonyme Funktion erneut aufgerufen und liefert ein neues Formular zurück.

Es bleibt nur noch sicherzustellen, dass das Formular auch wirklich das richtige Produkt in den Warenkorb legt – derzeit ist das Formular bei jedem Produkt identisch. Dabei hilft uns eine Eigenschaft des Multipliers (und generell jeder Komponenten-Factory im Nette Framework): Jede Factory erhält als erstes Argument den Namen der erzeugten Komponente. Die Factory des Multipliers erhält darüber hinaus als zweites Argument die Instanz des Multipliers selbst. In unserem Fall ist das erste Argument $item->id, also genau die Information, die wir brauchen. Es genügt daher, die Erstellung des Formulars leicht anzupassen:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function (string $itemId) {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('amount', 'Anzahl:')
			->setRequired();
		$form->addHidden('itemId', $itemId);
		$form->addSubmit('send', 'In den Warenkorb');
		return $form;
	});
}