Riutilizzare i moduli in più luoghi
Come riutilizzare lo stesso modulo in più punti senza duplicare il codice? Questo è molto facile da fare in Nette e ci sono diversi modi tra cui scegliere.
Fabbrica di moduli
Creiamo una classe che possa creare un modulo. Una classe di questo tipo è chiamata factory. Nel luogo in cui vogliamo usare il form (per esempio, nel presentatore), richiediamo il factory come dipendenza.
Parte del factory è il codice che passa i dati per un'ulteriore elaborazione quando il form viene inviato con successo. Di
solito al livello del modello. Inoltre, controlla se tutto è andato bene e restituisce eventuali errori al form. Il modello
nell'esempio seguente è rappresentato dalla classe Facade
:
use Nette\Application\UI\Form;
class EditFormFactory
{
public function __construct(
private Facade $facade,
) {
}
public function create(/* parameters */): Form
{
$form = new Form;
// aggiungere elementi al form
$form->addSubmit('send', 'Submit');
$form->onSuccess[] = [$this, 'processForm'];
return $form;
}
public function processForm(Form $form, array $values): void
{
try {
// elaborazione del form
$this->facade->process($values);
} catch (AnyModelException $e) {
$form->addError('...');
}
}
}
Naturalmente, il factory può essere parametrico, cioè può ricevere parametri che influiscono sull'aspetto del form creato.
Dimostreremo ora di passare il factory al presentatore. Per prima cosa, lo scriviamo nel file di configurazione:
services:
- EditFormFactory
e poi lo richiediamo al presentatore. Segue anche la fase successiva di elaborazione del modulo inviato, ovvero il reindirizzamento alla pagina successiva:
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;
}
}
Poiché il reindirizzamento è gestito dal gestore del presentatore, il componente può essere utilizzato in più luoghi e reindirizzato altrove in ogni luogo.
Componente con modulo
Un altro modo è quello di creare un nuovo componente che contenga un modulo. Questo ci dà la possibilità di rendere il modulo in un modo specifico, ad esempio, dato che il componente include un modello. Oppure si possono usare segnali per la comunicazione AJAX e il caricamento di informazioni nel modulo, ad esempio per il completamento automatico, ecc.
use Nette\Application\UI\Form;
class EditControl extends Nette\Application\UI\Control
{
public array $onSave = [];
public function __construct(
private Facade $facade,
) {
}
protected function createComponentForm(): Form
{
$form = new Form;
// aggiungere elementi al form
$form->addSubmit('send', 'Submit');
$form->onSuccess[] = [$this, 'processForm'];
return $form;
}
public function processForm(Form $form, array $values): void
{
try {
// elaborazione del form
$this->facade->process($values);
} catch (AnyModelException $e) {
$form->addError('...');
return;
}
// invocazione dell'evento
$this->onSave($this, $values);
}
}
Successivamente, creeremo il factory che produrrà questo componente. Basta scrivere la sua interfaccia:
interface EditControlFactory
{
function create(): EditControl;
}
E aggiungerla al file di configurazione:
services:
- EditControlFactory
Ora possiamo richiedere il factory e usarlo nel presenter:
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');
// oppure reindirizzare al risultato della modifica, ad esempio:
// $this->redirect('detail', ['id' => $data->id]);
};
return $control;
}
}