Form::cleanErrors() neodstraní chyby z prvků formuláře

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

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í:

  1. ve Form::cleanErrors() volat stejnou metody i ze všech potomků
  2. 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
+
0
-

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.

mkrause
Člen | 20
+
0
-

Fajn, díky za úpravu :)