Závislé selectboxy: snadná úloha v čistém Nette a JS
- David Grudl
- Nette Core | 8254
Závislé selectboxy jsou velmi snadná úloha na řešení v čistém Nette a JS.
Nejprve si připravím nějaký datový model, který mi bude vracet položky pro hlavní (main) select box a pro podřízený (dependent):
Dále nějaký EndpointPresenter, prostě API, abych ty položky mohl tahat i na straně prohlížeče jako JSON:
No a teď udělám formulář se dvěma selectboxy, které provážu.
Položky do podřízeného dávám až v onAnchor
(příp.
onValidate
), tedy ve chvíli, kdy formulář už zná hodnoty
odeslané uživatelem, což v době vytváření formuláře
ještě neví.
Tohle by už mělo samo o sobě fungovat (i bez JS), tak, že uživatel vybere první položku, odešle formulář, vybere druhou a znovu odešle.
Doplním JS a AJAX. A tím nejčistějším způsobem, tj. do formuláře
pouze přidám data-
atributy, ve kterých si pošlu do HTML (a
potažmo JS) informaci, které selectboxy jsou provázané (hlavní select bude
mít v atributu data-dependent
název podřízeného) a z jakého
URL získám položky (zapíšu do data-url
), abych mohl následně
provázání vyřešit i v JavaScriptu:
A zbývá napsat obslužný JS. Dnes se to dá snadno udělat i bez jQuery,
v čistém JS. Následující kód je univerzální, není vázaný na
konkrétní dva selectboxy, ale prováže jakékoliv selectboxy na stránce,
stačí jim jen přidat ony dva data-
attributy.
A je to :)
- kralik
- Člen | 230
Super, už to zkouším.
Jak by toto bylo možné rozšířit o další 2 scénáře použití?
Pomohl by někdo?
- Jeden hlavní select box + dva další selectboxy na něm závislé
- tedy změní se hodnota v hlavním selectboxu a dojde k načtení položek do dvou dalších selectboxů
- 3 select boxy
- 1. hlavní – vybere se hodnota a načtou se data do 2. selectboxu
- 2. vybere se hodnota a dle ní se načtou data do 3. select boxu
- 3. vybere se hodnota
Děkuji :-)
Editoval kralik (12. 1. 2022 7:18)
- Milo
- Nette Core | 1283
Dá se to udělat mnoha způsoby. Například:
add A – do data-dependent neuložíš jednu hodnotu, ale pole hodnot, tedy htmlname každého závislého selectboxu. Následně v actionMyData() pošleš data jako dvouúrovňové pole. A nakonec v JS v change eventu to zase zpracuješ jako pole, tedy o jeden foreach více.
add B – stačí nastavit data atributy i u závislých selectboxů.
- David Grudl
- Nette Core | 8254
Tohle bylo v podstatě napsané z hlavy, nemám to odzkoušené :) Takže bych ještě počkal.
- kralik
- Člen | 230
Milo napsal(a):
Dá se to udělat mnoha způsoby. Například:
add A – do data-dependent neuložíš jednu hodnotu, ale pole hodnot, tedy htmlname každého závislého selectboxu. Následně v actionMyData() pošleš data jako dvouúrovňové pole. A nakonec v JS v change eventu to zase zpracuješ jako pole, tedy o jeden foreach více.
add B – stačí nastavit data atributy i u závislých selectboxů.
mohl bys ukázat přímo v příkladech pro scénáře A i B?
Díky
- Kamil Valenta
- Člen | 833
Proč to neuděláš jak psal @Milo ?
To není pomoc?
Příklad != vypracování implementace pro Tebe.
Ukaž jak jsi to použil a na čem jsi narazil.
- David Grudl
- Nette Core | 8254
Pokud bych měl více nezávislých na jednom hlavním, tak by návrh změnil, a místo aby hlavní odkazoval na jeden podřízený, tak by podřízení odkazovali na jeden hlavní.
PHP:
a JS:
- David Grudl
- Nette Core | 8254
Pokud by byla kaskáda tří selectboxů, tak prostě přidám třetí prvek
a doplním analogicky data atributy a $onAnchor. V případě způsobu
provázání dle přechozího komentáře s data-depends
by
to bylo:
Samozřejmě je potřeba do modelu a endpointu doplnit dalsi metody generujici data pro ten třetí prvek.
- Petr Parolek
- Člen | 458
@DavidGrudl trochu OT – bude kod funkční na PHP < 8.0? Jedná
se mi o syntaxy fn
- David Grudl
- Nette Core | 8254
Nepamatuju si od které verze existuje fn. Kde fn není, použije se obdoba s function. Základy programování v PHP tu snad neřešíme.
- David Grudl
- Nette Core | 8254
A nakonec, pokud je málo hodnot a nepotřebuju AJAX, tak není potřeba
vytvářet EndpointPresenter, všechny položky si vyexportuju do
$subItems
a vložím do data atributu data-items
:
a pak je načtu přímo:
(Zase vycházím z kodu, kde se vazba dělá přes
data-depends
)
- dsar
- Backer | 53
In my opinion having also an example with snippets would promote the Nette-way of doing AJAX stuff (especially for those ones that don't like JavaScript, like me) and furthermore simplify things for newbies (like above).
Even without snippets, since the form works even without JavaScript (a good thing), the code could be reduced by submitting the form and updating the whole form's body
- David Grudl
- Nette Core | 8254
@kralik v JS byla chyba, místo dependent.dataset.main má by dependent.dataset.depends
- kralik
- Člen | 230
David Grudl napsal(a):
A máš tam
$form->onSuccess[] = ...
?
ano, mám toto.
Ještě jsem to zkoušel a musel jsem do formuláře přidat fn i pro druhý selectbox.
Již se zdá, že to běhá v pořádku.
Jdu ještě vyzkoušet scénář B (se třemi vzájemně provázanými
selectboxy).
Pak jsem kdyžtak dám celé řešení.
Díky
Editoval kralik (19. 1. 2022 12:55)
- kralik
- Člen | 230
Super, funguje to krásně.
Níže shrnuji celé řešení.
Jeden hlavní selectbox a dva závislí
- celkem 3 selectboxy, změnou hodnoty 1. selectboxu dojde k načtení hodnot do dalších dvou selectboxů
PRESENTER
LATTE
Tři závislé selectbox
- celkem 3 selectboxy, změnou hodnoty 1. selectboxu dojde k načtení hodnot do 2. selectboxů
- změnou hodnoty ve 2. selectboxu dojde k načtení hodnot do 3. selectboxů
PRESENTER
LATTE
Děkuji všem za pomoc
- kralik
- Člen | 230
Ahoj,
prosím o radu.
Řeším následující scénář závislých selectboxů:
Ve form mám 4 select boxy ZÁVOD, ODDĚLENÍ, WORKFLOW, PODPIS
Výběrem hodnoty v sb ZÁVOD se načtou položky do ODDĚLENÍ a
WORKFLOW
Výběrem hodoty v sb WORKFLOW se načtou položky do PODPIS
Všechno závislé doplňování funguje.
Ale problém nastane když dojde k submitu formuláře.
Ten vrátí chybu „Please select a valid option“ na sb PODPIS.
Bohužel netuším proč.
Ve formuláři tato hodnota není požadována.
Formulář v presenteru
Latte
- kralik
- Člen | 230
Pepino napsal(a):
@kralik zkus tomu selectu nastavit
případně ještě
toto bohužel nepomohlo.
když dám do formuláře
Zruším tento řádek aby se mi nenačetly závislé hodnoty.
Následně vyberu v selectboxu podpis „Někdo“, tak se formulář submitne a data se předají.
Problém nastane pokud se mají položky selectboxu načíst v závislosti
na vybrané položce „wf“
Při zkoumání prvku jsou tam data Ajaxem správně načtená, do toho
selectboxu „podpis“.
Bohužel netuším kde je problém.
- dehtak
- Člen | 113
a jak ste vyresily problem s timhle ?
Nette\Forms\Controls\SelectBox
Takto zavisly seletbox vraci vzdy null
Vim udelat novou tridu seletbox a do ni napsat novou metodu getValue.
A samozrejme se musi upravit i metoda SetValue.
Ale to by ste do toho vaseho manualu "":https://blog.nette.org/…-javascriptu
na webu meli pridat !!! Protoze jinak je to nefunkcni !!
Asi tak nejak zhruba
PS : Misto toho minusovani by ste mohli napsat co tam mam blbe, vsak mam pravdu ze bez novy tridy to nebude fachat
Editoval dehtak (12. 7. 2022 14:36)
- kralik
- Člen | 230
Ahoj,
lze vyřešit „dvojí main závislé selectboxy“?
Narazím když bych chtěl dva nezávislé na sobě, ale závislé selectboxy,
vysvětlím.
1. Závislý main SelectBox
Závod na jehož výběru závisí selectBox Workflow.
→ výběrem Závodu se doplní položky
Workflow = toto funguje dobře.
2. Závislý main SelectBox
Dodavatel na jehož výběru závisí selectBox
Provozovna
→ výběrem 1. selectBoxu Závod se v Dodavateli ani v Provozovně nic
nestane
→ až s výběrem Dodavatel se doplní položky
Provozovna
Bohužel toto nemohu rozchodit.
Zkouším postup https://blog.nette.org/…-javascriptu ten funguje dobře na 1. Závislý SelectBox.
Ale druhý závislý SelectBoxu je bez reakce, ani se nevyvolá Ajax, při změne položky Dodavatel.
Myslím, že problém je v javascriptu, ale to netuším jak vyřešit.
javascript
Můžete mi poradit?
Díky
- vladimir.biro
- Člen | 163
Hello.
Mam malej problem. Zavisle selectboxy mi funguji v poradku, ale na druhej
selectbox (ten zavislej) mam napojene ->toggle() a toto uz nefunguje. Kdyz si
v zavislem selectboxu vyberu tu moznost, ktera zobrazuje dane #id, tak se
zobrazi, to je fajn, ale po zmene halvniho selectboxu, se zavislej selectbox
zmeni v dusledku nactenych novych hodnot, ale dane #id mi zustane zobrazene,
i kdyz dana addCondition() podminka uz neplati. Musim pak prepnout zavislej
selectbox rucne (a pak se pripadne vratit) a az pak #id zmizi.
Resil tohle nekdo pls?
Dekuju za jakekoli rady.
- Pepino
- Člen | 257
@vladimirbiro
Mělo by myslím stačit po změně hlavního selectboxu zavolat
Nette.toggleForm https://github.com/…etteForms.js#L563
Nebo možná nastavit na tom hlavím selectboxu taky toggle.
- Higr
- Člen | 23
Vytvořil jsem si formuláře podle zadání a vše funguje správně. Nicméně pokud formulář použiju pro editování záznamu, dostanu error Value ‚1‘ is out of allowed set [] in field… na
dělám neco špatně nebo je uvedený tutorial nepoužitelný pro
editování záznamu?
koukal jsem že se to řešilo tady ale asi neúspěšně https://forum.nette.org/…-setdefaults
Editoval Higr (21. 6. 2024 9:59)
- Šaman
- Člen | 2667
Higr napsal(a):
Vytvořil jsem si formuláře podle zadání a vše funguje správně. Nicméně pokud formulář použiju pro editování záznamu, dostanu error Value ‚1‘ is out of allowed set [] in field… na
dělám neco špatně nebo je uvedený tutorial nepoužitelný pro editování záznamu?
koukal jsem že se to řešilo tady ale asi neúspěšně https://forum.nette.org/…-setdefaults
Od boku: Když nastavuješ defaultní hodnoty, musíš vybrat z těch,
které formulář umožňuje vybrat. Tedy z nastavených dat těch inputů.
Takže v actionEdit musíš nastavit $dependent->setItems()
podle defaultní hodnoty nadřizeného selectu.
Protože v prázdném formuláři ten závislý select nemá žádné možnosti
a ty se mu nastaví pomocí ajaxu až po změně hlavního selectu. Ale ty mu
chceš při editaci nastavit hodnoty ihned, bez toho ajaxového načtení.
- Higr
- Člen | 23
Šaman napsal(a):
Higr napsal(a):
Vytvořil jsem si formuláře podle zadání a vše funguje správně. Nicméně pokud formulář použiju pro editování záznamu, dostanu error Value ‚1‘ is out of allowed set [] in field… na
dělám neco špatně nebo je uvedený tutorial nepoužitelný pro editování záznamu?
koukal jsem že se to řešilo tady ale asi neúspěšně https://forum.nette.org/…-setdefaultsOd boku: Když nastavuješ defaultní hodnoty, musíš vybrat z těch, které formulář umožňuje vybrat. Tedy z nastavených dat těch inputů. Takže v actionEdit musíš nastavit
$dependent->setItems()
podle defaultní hodnoty nadřizeného selectu.
Protože v prázdném formuláři ten závislý select nemá žádné možnosti a ty se mu nastaví pomocí ajaxu až po změně hlavního selectu. Ale ty mu chceš při editaci nastavit hodnoty ihned, bez toho ajaxového načtení.
Děkuji, takhle mi to funguje. Hodilo by se to dopsat do toho tutorialu. Viděl jsem několik lidí, kteří hledali řešení pro ten samý problém.
- Marek Znojil
- Člen | 90
U prvků, které dědí
Nette\Forms\Controls\ChoiceControl
můžeš metodou
checkDefaultValue(false)
vypnout kontrolu hodnot v seznamu, viz
poslední odstavec https://doc.nette.org/…rms/controls#….