Vylepšení serverové validace při ajaxovém zpracování formuláře
- medhi
- Generous Backer | 255
Mám formulář, odesílám ho ajaxově. Pomocí Najy jsem si udělal live validaci, která skvěle funguje. Jeden input ale musím validovat na serveru, protože se dotazuji databáze. Při chybě vracím tedy
$form['jmeno']->addError('zadejte jiné jméno.');
$this->redrawControl('formular');
return;
Ale to se mi úplně nelíbí, protože to invaliduje celý formulář, tedy zmizí mi focus z políčka a těžko se tam vrací a vůbec si říkám, proč invalidovat celý formulář, když chci jenom označit vadné pole. Řekl jsem si tedy, že si pouze v payloadu vrátím seznam chyb a ty si javascriptem označím ve formuláři, tedy na serveru:
$this->payload->formErrors = $form->getErrors();
$this->sendPayload();
return;
No jo, ale ono to vrací seznam chyb bez udání, k jakým inputům jednotlivé chyby patří, protože $form[‚jmeno‘]->addError() zapomene, čeho se chyba týká: https://github.com/…eControl.php#L500
Moje otázka tedy zní, jestli by tam názvy controls nešly doplnit, abych si mohl udělat pěknou serverovou validaci, která mi nebude invalidovat formulář?
Moje naivní představa (BaseControl.php a Base):
/**
* Adds error message to the list.
* @param string|object $message
*/
public function addError($message, bool $translate = true): void
{
$this->errors[$this->getHtmlId()] = $translate ? $this->translate($message) : $message;
}
Nebo mi uniká jiný způsob?
Díky moc
- nightfish
- Člen | 518
Když zavoláš
$form['jmeno']->addError('zadejte jiné jméno.');
, tak se
nejedná o Form::addError()
, nýbrž o
BaseControl::addError()
. Každý prvek formuláře si errory
pamatuje pro sebe, avšak volání Form::getErrors()
je skrz
Container::getErrors()
zmerguje do jednoho pole.
Řešením by mohlo být inspirovat se v Container::getErrors() a poskládat si vlastní pole s chybami po jednotlivých polích formuláře, které si vrátíš v payloadu.
- medhi
- Generous Backer | 255
nightfish napsal(a):
Když zavoláš
$form['jmeno']->addError('zadejte jiné jméno.');
, tak se nejedná oForm::addError()
, nýbrž oBaseControl::addError()
. Každý prvek formuláře si errory pamatuje pro sebe, avšak voláníForm::getErrors()
je skrzContainer::getErrors()
zmerguje do jednoho pole.
Já vím.
>
Řešením by mohlo být inspirovat se v Container::getErrors() a poskládat si vlastní pole s chybami po jednotlivých polích formuláře, které si vrátíš v payloadu.
Ale právě nevidím způsob, jak to udělat bez zásahu do FW. Jak si to pole poskládám sám i s informací, o jaké prvky jde?
- nightfish
- Člen | 518
@medhi
Takto jsem to myslel:
public function doSomething(): void
{
/** @var Form $form */
$form = $this['form'];
$this->payload->formErrors = $this->getFormErrors($form);
$this->sendPayload();
}
private function getFormErrors(Form $form): array
{
$errors = [];
$errors['form'] = $form->getOwnErrors();
/** @var IControl $control */
foreach ($form->getControls() as $control) {
if ($control instanceof BaseControl && $control->hasErrors()) {
// pokud chces vsechny chyby polozky formulare, vracene jako pole
$errors[$control->getName()] = $control->getErrors();
// NEBO
// pokud ti staci string, kdy je vic pripadnych chyb k jedne polozce formulare
// concatnuto do jednoho retezce
$errors[$control->getName()] = $control->getError();
}
}
// obsahuje klice:
// "form" - chyby, ktere pridas pomoci $form->addError()
// "jmeno" - chyby, ktere pridas pomoci $form['jmeno']->addError()
return $errors;
}