Multiplikator: Dynamische Komponenten

Ein Werkzeug zur dynamischen Erstellung von interaktiven Komponenten

Beginnen wir mit einem typischen Problem: Wir haben eine Liste von Produkten auf einer E-Commerce-Website und möchten jedes Produkt mit einem Formular in den Warenkorb legen begleiten. Eine Möglichkeit ist, die gesamte Liste in ein einziges Formular zu verpacken. Eine bequemere Möglichkeit ist die Verwendung von Nette\Application\UI\Multiplier.

Multiplier ermöglicht es Ihnen, eine Fabrik für mehrere Komponenten zu definieren. Sie basiert auf dem Prinzip der verschachtelten Komponenten – jede Komponente, die von Nette\ComponentModel\Container erbt, kann andere Komponenten enthalten.

Siehe Komponentenmodell in der Dokumentation.

Multiplier stellt eine übergeordnete Komponente dar, die ihre Kinder dynamisch über den im Konstruktor übergebenen Callback erzeugen kann. Siehe Beispiel:

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

In der Vorlage können wir ein Formular für jedes Produkt darstellen – und jedes Formular wird tatsächlich eine einzigartige Komponente sein.

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

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

Das Argument, das an den {control} -Tag übergeben wird, lautet:

  1. eine Komponente erhalten shopForm
  2. und ihr Kind zurückgeben $item->id

Beim ersten Aufruf von 1. ist die Komponente shopForm noch nicht vorhanden, daher wird die Methode createComponentShopForm aufgerufen, um sie zu erstellen. Eine anonyme Funktion, die als Parameter an Multiplier übergeben wird, wird dann aufgerufen und ein Formular wird erstellt.

In den folgenden Iterationen des foreach wird die Methode createComponentShopForm nicht mehr aufgerufen, da die Komponente bereits existiert. Da wir aber auf ein anderes Kind verweisen ($item->id variiert zwischen den Iterationen), wird erneut eine anonyme Funktion aufgerufen und ein neues Formular erstellt.

Als Letztes müssen wir sicherstellen, dass das Formular tatsächlich das richtige Produkt zum Warenkorb hinzufügt, denn im aktuellen Zustand sind alle Formulare gleich und wir können nicht unterscheiden, zu welchen Produkten sie gehören. Hierfür können wir die Eigenschaft von Multiplier (und generell von jeder Komponentenfabrikmethode im Nette Framework) nutzen, dass jede Komponentenfabrikmethode den Namen der erstellten Komponente als erstes Argument erhält. In unserem Fall wäre das $item->id, was genau das ist, was wir brauchen, um einzelne Produkte zu unterscheiden. Alles, was Sie tun müssen, ist, den Code für die Erstellung des Formulars zu ändern:

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