Form::cleanErrors() neodstraní chyby z prvků formuláře
- mkrause
- Člen | 20
Ahoj Davide,
v jednom specifickém případě používáme public metodu
cleanErrors
v třídě Form
, ovšem výsledkem je
poměrně matoucí chování. Jde o případ, kdy provádíme jisté manipulace
s daty mezi voláním $form->isSubmitted()
a
$form->isValid()
. isSubmitted
totiž už interně
provede validaci, která může skončit s chybami, ty ale následné
zpracování může odstranit (konkrétně jde o to, že čistíme HTML
vložené do WYSIWYG editoru z Wordu od jeho balastu). Proto provedeme
zhruba toto:
if ($form->isSubmitted()) {
$form->cleanErrors();
$form["html"]->setValue($this->cleanHtml($form["html"]->getValue());
if ($form->isValid()) {
...
}
}
Pokud je HTML i po pročištění nevalidní, případně existují jiné
chyby, volání $form->isValid()
by je teoreticky mělo opět ve
formuláři nastavit. Bohužel se tak nestane, protože`
$form->cleanErrors()` vyčistí jen svoje pole chyb, ale ne už interní pole
chyb potomků (formulářových prvků). U těch pak druhá validace chybu
zjistí, ale chyba se považuje za duplicitní a už se nepřidává ani
nepropaguje do rodiče, tedy do formuláře. Napadají mě dvě řešení:
- ve
Form::cleanErrors()
volat stejnou metody i ze všech potomků - ve
FormControl::addError()
aplikovat kontrolu duplicity chybových hlášek pouze pro účely přidání do interního pole$errors
, ale chybu vždy propagovat do rodiče a kontrolu duplicity v globálním pohledu celého formuláře ponechat na něm
Co je lepší nechám na Tobě. My jsme si prozatím interně opatchovali
Form, takže metoda cleanErrors
vypadá takto:
/**
* @return void
*/
public function cleanErrors()
{
$this->errors = array();
foreach ($this->getGroups() as $group) {
if (!$group->getControls()) {
continue;
}
foreach ($group->getControls() as $control) {
$control->cleanErrors();
}
}
foreach ($this->getControls() as $control) {
$control->cleanErrors();
}
$this->valid = NULL;
}
- David Grudl
- Nette Core | 8228
Asi bude vhodnější to druhé řešení, protože by pak vznikla nekonzistence, proč Form::getErrors() a hasError() taky neprochází potomky. Je to implementované.
ps. ten cyklus foreach ($this->getGroups()
by tam ani nemusel
být, $this->getControls()
by mělo projít všechny
komponenty.