Nette Documentation Preview

syntax
Multiplier: Динамічні компоненти
********************************

Інструмент для динамічного створення інтерактивних компонентів.

Давайте почнемо з типової проблеми: у нас є список товарів на сайті електронної комерції, і ми хочемо супроводити кожен товар формою *додати до кошика*. Один зі способів - обернути весь лістинг в одну форму. Більш зручним способом є використання [api:Nette\Application\UI\Multiplier].

Multiplier дозволяє визначити фабрику для декількох компонентів. Він заснований на принципі вкладених компонентів - кожен компонент, що успадковує від [api:Nette\ComponentModel\Container], може містити інші компоненти.

Див. [модель компонента |components#Components in Depth] в документації.

Multiplier являє собою батьківський компонент, який може динамічно створювати свої дочірні компоненти, використовуючи зворотний виклик, переданий у конструкторі. Див. приклад:

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

У шаблоні ми можемо відобразити форму для кожного товару - і кожна форма дійсно буде унікальним компонентом.

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

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

Аргумент, переданий у тег `{control}`, свідчить:

1. отримати компонент `shopForm`
2. повернути своєму нащадку `$item->id`

При першому виклику **1.** компонент `shopForm` ще не існує, тому для його створення викликається метод `createComponentShopForm`. Потім викликається анонімна функція, передана як параметр у Multiplier, і створюється форма.

У наступних ітераціях `foreach` метод `createComponentShopForm` більше не викликається, оскільки компонент уже існує. Але оскільки ми посилаємося на іншого нащадка (`$item->id` варіюється між ітераціями), анонімна функція викликається знову і створюється нова форма.

Останнє, що потрібно зробити, це переконатися, що форма справді додає правильний товар до кошика, тому що в поточному стані всі форми рівні, і ми не можемо розрізнити, до яких продуктів вони належать. Для цього ми можемо використовувати властивість класу Multiplier (і взагалі будь-якого методу фабрики компонентів у фреймворку Nette), що кожен метод фабрики компонентів отримує ім'я створеного компонента як перший аргумент. У нашому випадку це буде `$item->id`, що саме те, що нам потрібно, щоб розрізняти окремі товари. Все, що вам потрібно зробити, це змінити код для створення форми:

```php
protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function ($itemId) {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('amount', 'Количество:')
			->setRequired();
		$form->addHidden('itemId', $itemId);
		$form->addSubmit('send', 'Добавить в корзину');
		return $form;
	});
}
```

Multiplier: Динамічні компоненти

Інструмент для динамічного створення інтерактивних компонентів.

Давайте почнемо з типової проблеми: у нас є список товарів на сайті електронної комерції, і ми хочемо супроводити кожен товар формою додати до кошика. Один зі способів – обернути весь лістинг в одну форму. Більш зручним способом є використання Nette\Application\UI\Multiplier.

Multiplier дозволяє визначити фабрику для декількох компонентів. Він заснований на принципі вкладених компонентів – кожен компонент, що успадковує від Nette\ComponentModel\Container, може містити інші компоненти.

Див. модель компонента в документації.

Multiplier являє собою батьківський компонент, який може динамічно створювати свої дочірні компоненти, використовуючи зворотний виклик, переданий у конструкторі. Див. приклад:

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

У шаблоні ми можемо відобразити форму для кожного товару – і кожна форма дійсно буде унікальним компонентом.

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

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

Аргумент, переданий у тег {control}, свідчить:

  1. отримати компонент shopForm
  2. повернути своєму нащадку $item->id

При першому виклику 1. компонент shopForm ще не існує, тому для його створення викликається метод createComponentShopForm. Потім викликається анонімна функція, передана як параметр у Multiplier, і створюється форма.

У наступних ітераціях foreach метод createComponentShopForm більше не викликається, оскільки компонент уже існує. Але оскільки ми посилаємося на іншого нащадка ($item->id варіюється між ітераціями), анонімна функція викликається знову і створюється нова форма.

Останнє, що потрібно зробити, це переконатися, що форма справді додає правильний товар до кошика, тому що в поточному стані всі форми рівні, і ми не можемо розрізнити, до яких продуктів вони належать. Для цього ми можемо використовувати властивість класу Multiplier (і взагалі будь-якого методу фабрики компонентів у фреймворку Nette), що кожен метод фабрики компонентів отримує ім'я створеного компонента як перший аргумент. У нашому випадку це буде $item->id, що саме те, що нам потрібно, щоб розрізняти окремі товари. Все, що вам потрібно зробити, це змінити код для створення форми:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function ($itemId) {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('amount', 'Количество:')
			->setRequired();
		$form->addHidden('itemId', $itemId);
		$form->addSubmit('send', 'Добавить в корзину');
		return $form;
	});
}