Lepší detekce zrušení formuláře
- Lawondyss
- Člen | 106
Mám komponentu
use Nette\Application\UI;
class ExampleForm extends UI\Control
{
public $onSuccess = array();
public function createComponentForm()
{
$form = new UI\Form;
$form->onSuccess[] = $this->processForm;
$form->addText('example', 'Example text')
$form->addSubmit('save', 'Save');
$form->addSubmit('cancel', 'Cancel')
->setValidationScope(false);
return $form;
}
public function processForm(UI\Form $form)
{
if (!$form['cancel']->isSubmittedBy()) {
$values = $form->getValues();
dump($values);
}
$this->onSuccess($form);
}
}
kterou používám v presenteru
class ExamplePresenter extends UI\Presenter
{
public function createComponentExampleForm()
{
$form = $this->exampleFormFactory->create();
$form->onSuccess[] = function (UI\Form $form) {
if ($form->isValid()) {
if (!$form['cancel']->isSubmittedBy()) {
$this->flashMessage('Success!', 'success');
}
$this->redirect('default');
}
};
return $form;
}
}
Trápí mě to, že v presenteru musím znát jméno tlačítka cancel, protože na něm ověřuji, zdali byl formulář odeslán přes něj. Na druhou stranu následné kroky (hláška, přesměrování) do formuláře cpát nechci.
Je nějaký lepší způsob, jak tohle řešit?
- David Kudera
- Člen | 455
Co třeba udělat si vedle onSuccess
události ještě
onCancel
, v tom formu podle toho upravit volání a v presenteru
poslouchat na obě události?
- hranicka
- Člen | 23
Jestli jsem tě správně pochopil, tak chceš z vnějšku té Control
reagovat na chování toho formuláře.
Můžeš přidal ještě další události:
/** @var callable */
public $onSuccess = [];
/** @var callable */
public $onCancel = [];
protected function createComponentForm()
{
// ...
$form->addSubmit('cancel', 'Cancel')
->setValidationScope(FALSE);
$form->onSuccess[] = $this->formSuccess;
}
public function formSuccess(Form $form)
{
if ($form['cancel']->isSubmittedBy()) {
$this->onCancel($form);
} else {
$this->onSuccess($form);
}
}
Pak bys mohl v tom presenteru jen navěsit callbacky na události
onSuccess
a onCancel
té Control (nikoliv
formuláře):
onSuccess
by volalo jen v případě úspěšného formuláře, který nebyl odeslán tlačítkem „cancel“onCancel
by se volalo v případě, že by byl odeslán tlačítkem „cancel“
Editoval hranicka (1. 7. 2014 21:25)
- Šaman
- Člen | 2666
@Lawondyss: Proč? On to stejně ví, bude s ním tohle:
$form->onSuccess[] = $this->processForm;
Tak proč by rovnou nemohl říct, že každé tlačítko se bude obsluhovat
jinou metodou?
<?php
$form->addSubmit('ok', 'Ok')
->onClick[] = $this->processForm;
$form->addSubmit('cancel', 'Cancel')
->setValidationScope(FALSE)
->onClick[] = $this->cancelForm;
?>
Samozřejmě si můžeš připravit formulář bez tlačítek a tohle přidat až v továrničce, pokud chceš formulář obsluhovat jen zvenku.
Editoval Šaman (2. 7. 2014 0:19)
- besanek
- Člen | 128
A kdo říká že by měl přesměrovávat? Budeš mít dvě události onSuccess a onCancel
$form->addSubmit('ok', 'Ok')
->onClick[] = function($form) {
$this->onSuccess($form);
};
$form->addSubmit('cancel', 'Cancel')
->setValidationScope(FALSE)
->onClick[] = function(UI\Form $form) {
$this->onCancel($form);
};
A pak v presenteru použiješ.
public function createComponentExampleForm()
{
$form = $this->exampleFormFactory->create();
$form->onSuccess[] = function (UI\Form $form) {
$this->flashMessage('Success!', 'success');
$this->redirect('default');
};
$form->onCancel[] = function (UI\Form $form) {
$this->redirect('cancel');
};
return $form;
}
- MartinitCZ
- Člen | 580
Proč si to tak stěžuješ?
Já ve většině případů mám funkce zpracování přímo u formuláře a
nikdy stím nebyl problém.
Naopak se tím většině problémů vyhneš.
- Šaman
- Člen | 2666
Lawondyss napsal(a):
@šaman Jenže proč by měl formulář vědět, kam následně uživatele přesměrovat. To odporuje myšlence znovupoužitelnosti. Takže formulář nechám něco uložit a následně v presenteru nadefinuju, co se má po uložení stát.
Chápu, ale:
- Dokud jsi používal jednu metodu
processForm()
, tak jsi narážel na stejný problém, ne? - Obslužné metody se dají vrstvit, proto se přidávají do pole. Takže ty
můžeš mít obsluhu částečně ve formuláři i v presenteru. Kdysi jsem
to tak používal. Dokonce jsem si ve formuláři zjišťoval, jestli je tato
obslužná metoda poslední a pokud ano, prováděl jsem
redirect('this')
, pokud za ní následovala nějaká další (ta presenterová), nechal jsem redirect na ni. Z presenteru dokonce můžeš pole událostí úplně vyčistit a navěsit tam jen vlastní obsluhu.
P.S. Jen pozor na to, že obslužné události navěšené na tlačítko nedostávají jako parametr Form, ale SubmitButton. Resp. ve starším Nette tomu tak bylo a poslední rok, dva jsem to nepoužil.
<?php
public function onSuccess(\Nette\Forms\Controls\SubmitButton $button)
{
$form = $button->form;
// ...
}
?>
- MartinitCZ
- Člen | 580
Jen dodám, že v Nette 2.2 je v dané funkci ještě druhý parameter $values. ;)
<?php
public function onSuccess(\Nette\Forms\Controls\SubmitButton $button, $values)
{
$form = $button->form;
// ...
// $values instead of $form->getValues();
}