Multiplier: динамични компоненти
Инструмент за динамично създаване на интерактивни компоненти
Да започнем с типичен пример: имаме списък със стоки в електронен магазин, като за всяка искаме да покажем формуляр за добавяне на стоката в количката. Един от възможните варианти е да обвием целия списък в един формуляр. Много по-удобен начин обаче ни предлага Nette\Application\UI\Multiplier.
Multiplier позволява удобно да се дефинира фабрика за множество компоненти. Работи на принципа на вложените компоненти – всеки компонент, наследяващ Nette\ComponentModel\Container, може да съдържа други компоненти.
Вижте главата за компонентния модел в документацията или лекцията от Honza Tvrdík.
Същността на Multiplier е, че той действа като родител, който може да създава своите потомци динамично с помощта на callback, предаден в конструктора. Вижте примера:
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function () {
$form = new Nette\Application\UI\Form;
$form->addInteger('count', 'Брой стоки:')
->setRequired();
$form->addSubmit('send', 'Добави в количката');
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) след това се извиква
фабриката на конкретния формуляр – което е анонимната функция, която
предадохме на Multiplier в конструктора.
В следващата итерация на foreach методът createComponentShopForm
вече няма
да бъде извикван (компонентът съществува), но тъй като търсим друг
негов потомък ($item->id
ще бъде различно във всяка итерация),
отново ще бъде извикана анонимната функция и ще ни върне нов
формуляр.
Единственото, което остава, е да осигурим, че формулярът ще добави в
количката наистина тази стока, която трябва – в момента формулярът
при всяка стока е напълно идентичен. Ще ни помогне свойството на Multiplier
(и общо на всяка фабрика за компонент в Nette Framework), а именно това, че всяка
фабрика като свой първи аргумент получава името на създавания
компонент. В нашия случай това ще бъде $item->id
, което е точно
информацията, от която се нуждаем. Достатъчно е леко да променим
създаването на формуляра:
protected function createComponentShopForm(): Multiplier
{
return new Multiplier(function ($itemId) {
$form = new Nette\Application\UI\Form;
$form->addInteger('count', 'Брой стоки:')
->setRequired();
$form->addHidden('itemId', $itemId);
$form->addSubmit('send', 'Добави в количката');
return $form;
});
}