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}
, свідчить:
- отримати компонент
shopForm
- повернути своєму нащадку
$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;
});
}