Ponowne wykorzystanie formularzy w wielu miejscach
Jak ponownie wykorzystać ten sam formularz w wielu miejscach i nie powielać kodu? W Nette jest to naprawdę proste i masz więcej sposobów do wyboru.
Fabryka Form
Stwórzmy klasę, która potrafi stworzyć formularz. Taka klasa nazywana jest fabryką. W miejscu, w którym chcemy użyć formularza (np. w prezenterze), żądamy fabryki jako zależności.
Część fabryki to kod, który przekazuje dane do dalszego przetwarzania, gdy formularz zostanie pomyślnie przesłany.
Zazwyczaj do warstwy modelu. Sprawdza również, czy wszystko poszło dobrze i przekazuje wszelkie błędy z powrotem do formularza. Model w poniższym przykładzie
jest reprezentowany przez klasę Facade
:
use Nette\Application\UI\Form;
class EditFormFactory
{
public function __construct(
private Facade $facade,
) {
}
public function create(/* parametry */): Form
{
$form = new Form;
// přidáme prvky do formuláře
$form->addSubmit('send', 'Odeslat');
$form->onSuccess[] = [$this, 'processForm'];
return $form;
}
public function processForm(Form $form, array $values): void
{
try {
// zpracování formuláře
$this->facade->process($values);
} catch (AnyModelException $e) {
$form->addError('...');
}
}
}
Fabryka może być oczywiście parametryczna, tzn. może przyjmować parametry, które wpływają na tworzony przez nią formularz.
Teraz pokażemy, jak przekazać fabrykę do prezentera. Najpierw zapisujemy ją do pliku konfiguracyjnego:
services:
- EditFormFactory
A następnie zażądać go w prezenterze. Kolejnym etapem przetwarzania przesłanego formularza jest przekierowanie na kolejną stronę:
class MyPresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private EditFormFactory $formFactory,
) {
}
protected function createComponentEditForm(): Form
{
$form = $this->formFactory->create();
$form->onSuccess[] = function (Form $form) {
$this->redirect('this');
};
return $form;
}
}
Ponieważ przekierowanie jest obsługiwane przez handler prezentera, komponent może być używany w wielu miejscach i przekierowany do innego miejsca w każdym z nich.
Komponent z formą
Inną opcją jest stworzenie nowego komponentu, który zawiera formularz. Daje nam to możliwość np. renderowania formularza w określony sposób, ponieważ komponent zawiera szablon. Lub możemy użyć sygnałów do komunikacji AJAX i ładowania informacji do formularza, na przykład do podpowiedzi itp.
use Nette\Application\UI\Form;
class EditControl extends Nette\Application\UI\Control
{
public $onSave;
public function __construct(
private Facade $facade,
) {
}
protected function createComponentForm(): Form
{
$form = new Form;
// přidáme prvky do formuláře
$form->addSubmit('send', 'Odeslat');
$form->onSuccess[] = [$this, 'processForm'];
return $form;
}
public function processForm(Form $form, array $values): void
{
try {
// zpracování formuláře
$this->facade->process($values);
} catch (AnyModelException $e) {
$form->addError('...');
return;
}
// vyvolání události
$this->onSave($this, $values);
}
}
Stworzymy jeszcze fabrykę, która będzie produkowała ten komponent. Wystarczy napisać jego interfejs:
interface EditControlFactory
{
function create(): EditControl;
}
I dodaj go do pliku konfiguracyjnego:
services:
- EditControlFactory
A teraz możemy zażądać fabryki i użyć jej w prezenterze:
class MyPresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private EditControlFactory $controlFactory,
) {
}
protected function createComponentEditForm(): Form
{
$control = $this->controlFactory->create();
$control->onSave[] = function (EditControl $control, $data) {
$this->redirect('this');
// lub przekierować na wynik edycji, np:
// $this->redirect('detail', ['id' => $data->id]);
};
return $control;
}
}