při addError v onClick se volá i onSuccess

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
snake.aas
Člen | 25
+
0
-

nette: 2.0.12 (ze sandboxu)
php: 5.4.15

Mějme takovouhle definici komponenty

public function createComponentTestForm() {
		$form = new Nette\Application\UI\Form();
		$form->addText('a', 'Text');
		$form->addSubmit('send')
			->onClick[] = $this->click;

		$form->onSuccess[] = $this->success;

		return $form;
	}

	public function click(Nette\Forms\Controls\Button $button) {
		dump('button clicked event fired');
		$button->addError('This is a error');
	}

	public function success(Nette\Application\UI\Form $form) {
		dump('form success event fired');
	}

Když odešlu formulář, tak jako odpověď dostanu
„button clicked event fired“ (26)
„form success event fired“ (24)
This is a error

Přitom bych očekával, že když v handleru onClick přidám chybu, tak se mi už nevolá handler onSuccess (protože formulář v tomhle stavu už není success)

Neuniká mi nějaká feature, proč to takhle je?

Řeším to, protože mám save a cancel tlačítko a při odeslání pomocí save kontroluju správnost a v onSuccess už jen přesměruju, takhle to ale přesměruje i když je formulář špatně vyplněný

leninzprahy
Člen | 150
+
0
-

zkusil bych chybu přidat celému formu, ne jen buttonu

public function click(Nette\Forms\Controls\Button $button) {
    dump('button clicked event fired');
    $button->form->addError('This is a error');
}
snake.aas
Člen | 25
+
0
-

jo, souhlasím… nicméně výsledek je pořád stejný

pepakriz
Člen | 246
+
0
-

V onClick eventu už je na přidávání erroru pozdě. Buďto využij validátor pro input a nebo událost onValidate.

snake.aas
Člen | 25
+
0
-

Když budu v onClick například vkládat uživatele, který už je zavedený (unique index).
Tak namísto toho abych se pokusil vložit uživatele a zachytil vyjímku, kterou nějak zpracuju, se budu muset dotazovat jestli takový uživatel je a pak ho v onClick vložit. Což je zbytečný dotaz navíc.

Zatím to obcházím tak, že v success extra kontroluju $form->isValid(), ale to se mi moc nelíbí.

pepakriz
Člen | 246
+
0
-

A co takhle použít transakci, v události onValidate uživatele vložit, když to vyhodí výjimku, přidat error a revertnout – a když ne, tak v onSuccess commitnout?

Také by mě zajímalo, jaká je best practice.

Milo
Nette Core | 1283
+
0
-

Čím byl formulář odeslán můžeš kontrolovat až v onSuccess[]:

public function success(Nette\Application\UI\Form $form) {
	if ($form['send']->isSubmittedBy()) {
		...
	}
}
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Co takhle použít jen onSuccess[] a cancelovací tlačítko nahradit třeba odkazem.

Nicméně je pravda, že jde o dobrý příklad, kdy by se hodilo přerušení řetězce událostí.

Editoval vojtech.dobes (11. 9. 2013 12:08)

Felix
Nette Core | 1196
+
0
-

vojtech.dobes napsal(a):

Nicméně je pravda, že jde o dobrý příklad, kdy by se hodilo přerušení řetězce událostí.

Imho je ten sled spravny. IMHO by to mel kontrolovat v onValidate nebo v onSuccess muzes taky.

Milo
Nette Core | 1283
+
0
-

V onValidate je podle mě moc brzo. Pokud by se jen kontrolovale neexistence uživatele SELECTem, tak než program dojde k onClick anebo onSuccess, někdo může uživatele vytvořit.

Formuláře, které provádí něco s modelem a mají více tlačítek, řeším takhle:

// voláno v onSuccess[]
public function successForm(UI\Form $form)
{
	if ($form['save']->isSubmittedBy()) {
		try {
			$this->model->createUser(....);
			$this->redirect('that');
		} catch (ModelException $e) {
			$form->addError($e->getMessage());
		}
	} else {
		$this->redirect('back');
	}
}
snake.aas
Člen | 25
+
0
-

Milo napsal(a):

V onValidate je podle mě moc brzo. Pokud by se jen kontrolovale neexistence uživatele SELECTem, tak než program dojde k onClick anebo onSuccess, někdo může uživatele vytvořit.

Formuláře, které provádí něco s modelem a mají více tlačítek, řeším takhle:

// voláno v onSuccess[]
public function successForm(UI\Form $form)
{
	if ($form['save']->isSubmittedBy()) {
		try {
			$this->model->createUser(....);
			$this->redirect('that');
		} catch (ModelException $e) {
			$form->addError($e->getMessage());
		}
	} else {
		$this->redirect('back');
	}
}

No a pokud používám továrničku na formulář podle dg tak přesměrovávat v továrničce nechci kvůli znovupoužitelnosti.

Takhle bych si navázal dvě události onSuccess, které se imho provedou v pořadí v jakém jsem je navázal (první bude „továrničkový“ success, pak v createComponent).
Ale stejně se provedou obě, takže i tak musím ve druhé ověřovat validitu, ni?

Milo
Nette Core | 1283
+
0
-

O továrničce jsi nic nepsal ;-) Tam to takhle hezky použít nejde, to je fakt.

snake.aas
Člen | 25
+
0
-

Milo napsal(a):

O továrničce jsi nic nepsal ;-) Tam to takhle hezky použít nejde, to je fakt.

Jasně, první post jsem ořezal na to nejnutnější, abych ukázal o co mi konkrétně jde.
Pak už jenom rozvíjel myšlenku :)

Asi se spokojím s isValid()