Prázdná hodnota MultiSelect při ajaxovém načtení položek
- Odo
- Člen | 48
Ahoj všem,
narazil jsem na problém s MultiSelectem při použití Select2, ale zřejmě to bude obecně platit pro jakékoliv načítání <option> ajaxem.
Následující kód funguje bez problémů (všechny položky zadám v konstruktoru):
$form->addMultiPicker('folder_ids', 'Přiřazení do složek', $this->model->getFolders())
->setRequired(false);
Následující kód způsobí, že při zpracování formuláře bude
$values->folder_ids = []
– položky načítám přes ajax až
při vykreslení šablony):
$form->addMultiPicker('folder_ids', 'Přiřazení do složek', [])
->setRequired(false);
Pokud konstruktoru předám pole uživatelem zvolených položek,
$values->folder_ids
mi vrací jen tyto hodnoty, nikdy ne ty
načtené ajaxem. Začínám tušit, že to asi bude mít nějakou souvislost
s validací nebo zpracováním formuláře – Nette si zřejmě myslí, že
položky načtené ajaxem nepatří mezi povolené hodnoty zadané
v konstruktoru MultiSelectu a tak je odmaže. Jakým způsobem to mohu
opravit?
Předem díky za rady!
Editoval Odo (20. 4. 2020 21:56)
- Odo
- Člen | 48
Problém jsem vystopoval až k nikde nepopsané proměnné / metodě
checkAllowedValues
/ checkDefaultValue
. Nicméně
i přes jakoukoliv snahu tam nacpat false
zpracování formuláře
zemře při validaci (javascriptem dodaná položka je mimo rozsah), takže do
metody onSuccess
se ani nedostanu :(
Splácal jsem hack, který před addSelect() přečte
getHttpData
a pokud hodnota není v datech, tak ji tam přidá.
Hodně ošklivé, ale celkem jednoduché řešení.
class BaseForm extends Nette\Application\UI\Form
{
// ...
function addTextSelect($label, $name, $data = [])
{
// pokud položka neexistuje, přidáme ji
$values = $this->getHttpData();
if (isset($values[$label])) {
$text = $values[$label];
if (!isset($data[$text]) && $text !== '') $data[$text] = $text;
}
// přidáme normální select
return parent::addSelect($label, $name, $data);
}
}
Nebo mě napadlo přidat skryté textové pole, přes které se bude hodnota selectu přenášet, což je z hlediska Nette asi čistější řešení, ale zase javascript navíc…
Mimochodem je tu docela dost vláken na toto téma, žádné s řešením.
Editoval Odo (29. 4. 2020 16:04)
- Šaman
- Člen | 2663
Nejspíš narážíš na stejný problém, jaký se řeší v závislých selectboxech. Ano, je nutné nastavit příjimacímu formuláři (tomu co bude na stránce po odeslání) platné hodnoty, jinak všechny pro něj neznámé hodnoty zahodí (kvůli bezpečnosti, mohou být podvržené).
Takže můžeš zkusit googlit zavislé formuláře v Nette – sám ale nevím, jestli všechna řešení zůstala stejná i pro nové Nette. Budu to muset odzkoušet. U těch závislých selectboxů je nutné nastavit do závislého selectu hodnoty podle toho, co je vybrané v nezavislém selectu, většinou přímo v továrně na formulář.
Pokud ty hodnoty ajaxem bereš úplně jinde a není možné je nastavit při
vytváření formuláře, pak je asi nejlepší tahat je z
getHttpData()
. Nebo použít ten tvůj hack, ale pokud může být
podvržená nebezpečna hodnota, tak by bylo dobré před přidáním té
hodnoty do formuláře nějak ji ošetřit.
Editoval Šaman (29. 4. 2020 16:41)
- Odo
- Člen | 48
Teď jsem si uvědomil, že vlastně potřebuji „autocomplete“, tj. uživatel zadá co chce, přičemž si může ušetřit čas výběrem z předdefinovaných položek. Tudíž „podvržení“ hodnoty uživatelem je žádané a bezpečné. Můžu to tudíž předělat na normální Text input, se kterým si pohraju v JS. Výhoda Select/MultiSelect pro mě byla v tom, že jsem si teoreticky mohl vybrat, jestli jim do konstruktoru nacpu položky, nebo je načtu až skriptem. Když to vyřeším přes Text, tak ty položky musím načíst přes AJAX vždy :)
Editoval Odo (29. 4. 2020 17:11)