Ztráta vybraných „radio“ možností při serverové validaci formuláře – inputy skrz vlastní Latte filtr
- MikKuba
- Člen | 83
Ahoj,
Mám formulář, ve kterém kromě klasických radio inputů, checkboxů a textových polí je také input, který se ale vytváří skrz Latte filtr – je uvnitř formuláře, odesílá se.
Jenže při validaci, kdy se kontroluje vyplněnost a případně vrací s neúspěchem takto:
return $this->onErrorAccess('Není vyplněna odpověď na povinnou otázku: '. $question->question);
tak při zpětném načtení formuláře zůstanou s odeslanými hodnotami
vyplněné text inputy, i klasické seznamy radio a checkboxy.
Jenže některé radio listy jsou zde pomocí Latte filtru, který případně
z textu na základě hodnot v data-values vypisují dané hodnoty jako
„tlačítka“ vedle sebe. No a tyto „radio“ možnosti se zpětně
nevyplní.
Filtr pracuje takto:
private function replaceSelectAnswer(string $content): string
{
$this->counter = 0;
return Strings::replace($content, '~<a(?<args>[^>]*data-widget="selectanswer"[^>]*)>.*?</a>~', function ($matches) {
$parameters = [
'values' => json_decode(htmlspecialchars_decode(Strings::match($matches['args'], '~data-values="([^"]*)"~')[1] ?? 0)),
];
$parameters['id'] = $this->id . "_" . ++$this->counter;
return $this->renderTemplate('selectanswer.latte', $parameters);
});
}
A šablona je vykresluje takto:
<label class="selectanswer-block">
<label>
<input class="selectanswer-input" type="radio" name="answer{$id}" value="{$values->option1}"/>
<span>{$values->option1}</span>
</label>
<label>
<input class="selectanswer-input" type="radio" name="answer{$id}" value="{$values->option2}"/>
<span>{$values->option2}</span>
</label>
</label>
Při zkoumání se u klasických radio listů těm předtím zvoleným možnostem nastaví „checked“ a ve formuláři zůstanou, ale těmto nikoliv.
Dokázal by mi prosím někdo poradit, čím to může být? Zkoušel jsem i přidat jQuery:
$( document ).ready(function() {
$('.selectanswer-input').click(function(){
$(this).attr('checked', 'checked');
});
});
kterým jsem si ty checked rovnou přidával už při klikání, ale po té validaci a vrácení s chybou se to stejně nezvolilo zpětně a atribut „checked“ se smazal.
Předem moc díky!
- MikKuba
- Člen | 83
dakur napsal(a):
@MikKuba A jak vykresluješ tu šablonu s tím filtrem?
Pokud se jedná o typ „selectanswer“, tak se volá ten filtr pro nahrazení, volá se takto:
{if $question->type === "selectanswer"}
{$question->question|exerciseTypes:$question->id|noescape}
{/if}
Nicméně tento problém se objevuje i u některých další prvků formuláře, proto spíš chystám skript, který před odesláním prvně zkontroluje, zda jsou všechny povinné inputy (ale nikoliv označené jako required) vyplněné a teprve potom to dovolí odeslat. I z hlediska zatížení, běží to totiž na sdíleném hostingu a nemá to dostatečnou kapacitu PHP procesů v momentě, kdy je tam nával několik desítek lidí v jeden okamžik, tak někteří musí request opakovat. Tímto teda trochu ušetřím requesty, že formulář se odešle skutečně až po vyplnění a nebude ho to vracet jako neúplný.
Editoval MikKuba (30. 3. 2021 8:53)
- dakur
- Člen | 493
Nevím, jak máš dělané ty ostatní prvky, ale pokud je to normálně
field v Nette Forms přes např. $form->addText()
, tak pak se
nemůžeš divit. Vlastně sis odpověděl sám:
Při zkoumání se u klasických radio listů těm předtím zvoleným možnostem nastaví „checked“ a ve formuláři zůstanou, ale těmto nikoliv.
Ve výchozím stavu Nette Forms zajišťují vykreslování HTML a dosazení správných hodnot/atributů do něj:
$form->addSelect('vyber', [1 => 'první položka', 2 => 'druhá položka']);
$form->setDefaultValues(['vyber' => 2]);
{control $select}
↓
<select name="vyber" id="frm-vyber">
<option value="1">první položka</option>
<option value="2" selected>druhá položka</option>
</select>
Pak existuje manual rendering v Nette Forms, kdy sice píšeš HTML, ale
pomocí makra n:name
propojíš toto HTML s Nette fieldy, takže
Nette zajistí dosazení správných hodnot/atributů:
<select n:name="neco" id="jine-id" />{* můžu libovolně přepisovat či přidávat atributy *}
↓
<select name="vyber" id="jine-id">
<option value="1">první položka</option>
<option value="2" selected>druhá položka</option>
</select>
Ty ale renderuješ „radio listy“ úplně manuálně, tj. vůbec
nevyužíváš pro tato pole Nette Forms, takže není nic, co by jim nastavilo
ten atribut checked
– musíš se o to postarat sám. Do
šablony tedy doplníš podmínku, kdy se má atribut checked vyrenderovat:
<label class="selectanswer-block">
<label>
<input class="selectanswer-input" type="radio" name="answer{$id}" value="{$values->option1}"{if $neco === $values->option1} checked{/if}/>
<span>{$values->option1}</span>
</label>
<label>
<input class="selectanswer-input" type="radio" name="answer{$id}" value="{$values->option2}"{if $neco === $values->option2} checked{/if}/>
<span>{$values->option2}</span>
</label>
</label>
Přičemž $neco
jsou data z HTTP požadavku, to si budeš
muset vytáhnout v presenteru.
Editoval dakur (30. 3. 2021 12:49)