Мултипликатор: динамични компоненти
Инструмент за динамично създаване на интерактивни компоненти.
Нека да започнем с типичен проблем: имаме списък с продукти в сайт за електронна търговия и искаме да придружим всеки продукт с формуляр за добавяне в количката. Един от начините е да обхванете целия списък в един формуляр. По-удобен начин е да използвате 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;
});
}