Vylepšení serverové validace při ajaxovém zpracování formuláře

medhi
Generous Backer | 255
+
0
-

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 | 472
+
0
-

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
+
0
-

nightfish napsal(a):

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.

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 | 472
+
0
-

@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;
}