Best practice: obsluha formulářů
 
- David Grudl
- Nette Core | 8285
Životní cyklus formuláře se skládá:
- z jeho definice
- nastavení výchozích hodnot
- vykreslení uživateli
- validace
- získání dat
Existují v podstatě dva způsoby, jak cyklus implementovat: s využitím událostí nebo bez.
Bez obsluhy událostí
Doporučuji tento vzor:
// definice
$form = new Form();
$form->addText('name', 'Your name:');
$form->addSubmit('ok', 'Send');
$form->addSubmit('cancel', 'Cancel');
// byl odeslán?
if ($form->isSubmitted()) {
	if ($form['cancel']->isSubmittedBy()) {
		// process cancelled
		redirect(...);
	}
	if ($form['ok']->isSubmittedBy() && $form->isValid()) {
		// submitted and valid
		save($form->getValues());
		redirect(...);
	}
} else {
	// první zobrazení, nastavíme výchozí hodnoty
	$form->setDefaults($defaults);
}
Tento způsob je vhodný pro použití v jednoduchých webových stránkách, kde se nevyužívá MVC.
S obsluhou událostí
Doporučuji tento vzor:
// definice
$form = new Form();
$form->addText('name', 'Your name:');
$form->addSubmit('ok', 'Send')
	->onClick[] = 'OkClicked'; // nebo 'OkClickHandler'
$form->addSubmit('cancel', 'Cancel')
	->setValidationScope(FALSE)
	->onClick[] = 'CancelClicked'; // nebo 'CancelClickHandler'
// alternativa:
$form->onSubmit[] = 'FormSubmitted'; // nebo 'FormSubmitHandler'
if (!$form->isSubmitted()) {
	// první zobrazení, nastavíme výchozí hodnoty
	$form->setDefaults($defaults);
}
// zavolej obslužné handlery, pokud je formulář odeslán
$form->fireEvents();
// obslužné handlery:
function OkClicked(SubmitButton $button)
{
	// submitted and valid
	save($form->getValues());
	redirect(...);
}
function CancelClicked(SubmitButton $button)
{
	// process cancelled
	redirect(...);
}
function FormSubmitted(Form $form)
{
	// manual processing
	if ($form['cancel']->isSubmittedBy()) ...
}
Tento způsob je vhodný pro použití v MVC implementacích jako Nette\Application.
Obslužný handler pro onSubmit lze použít v případě, kdy formulář nemá žádné nebo právě jedno tlačítko. V odstatních situacích bývá vhodnější využít handler onClick přímo na tlačítku.
Handler onClick se volá před handlerem onSubmit. Handlery se volají
pouze v případě, že je odeslání validní. Pokud
odeslání validní není, volají se handlery pro události
onInvalidClick a onInvalidSubmit. Uvnitř metody
OkClicked tedy není nutné ověřovat validitu formuláře. Naopak
metoda FormSubmitted může být zavolána i v případě
nevalidního formuláře, byl-li odeslán tlačítkem Cancel.
V případě, že formulář nebyl odeslán tlačítkem (například byl
odeslán přes JavaScript), nebo se tak tváří kvůli chybě v Internet
Exploreru, bude Nette za odesílací tlačítko považovat první tlačítko
formuláře. Tudíž obsluha přes události onClick je
spolehlivá.
Obslužné handlery se vyvolají při prvním volání metody
fireEvents(), při použití uvnitř Nette\Application vyvolání
zajistí samotný presenter.
Přesměrování
Po odeslání POST formuláře a zpracování dat vždy přesměrujte na další stránku (v presenteru metodou redirect). Zamezíte tak situaci, že uživatel stisknutím tlačítka F5 nebo procházením historie v prohlížeči omylem odešle formulář znovu.
Callback
V uvedených ukázkách jsou jako handlery použity funkce, samozřejmě
pokud píšete objektový kód, je vhodnější volat metody (zejména ve
spojení s Nette\Application). Handler je nutno zapsat jako PHP typ callback, takže v případě
použití v presenteru například jako
$form->onSubmit[] = array($this, 'FormSubmitted').
 
- Vitek Jezek
- hledá kolegy | 285
znesvetim tento Best practice otazkou – mohu nejak v obsluznych handlerech brat promene, ktere jsou v kodu pred zavolanim obsluznych handleru (tedy ve funkci, ktera tvori form/vola handlery)?
Zatim to obchazim pres persistentni parametry, ale urcite by to slo vice Nette (cti [vice ciste / elegantne / lepe]) : )
 
- David Grudl
- Nette Core | 8285
Pokud obslužné handlery představují metody objektu, tak můžeš používat třeba proměnné objektu.