Perzistentní parametry po odeslání formuláře v komponentě
- roman.campula
- Člen | 60
Zdravím,
už jsem si myslel, že perzistentním parametrům rozumím, ale asi
ještě ne.
Mám komponentu na výběr odpovědí k otázce (klasický test), celkem 10 otázek. Chci, abych po se výběru odpovědi odeslal ajaxem formulář, inkrementovalo se ID otázky a překreslila komponenta. Tím bych viděl druhou otázku a tak dále.
Místo toho však vidím stále první otázku. Předpokládám, že je to
tím, že po překreslení se v konstruktoru asi znovu nastaví
questionId = 1
. Jak mám tedy questionId
po odeslání
formuláře inkrementovat? Je potřeba to pak někde odchytávat
z parametrů URL?
Předem díky za pomoc, toto už řeším poněkolikáté v různých variantách a ještě se nezadařilo.
presenter (zjednodušeno)
komponenta (zjednodušeno)
- Marek Bartoš
- Nette Blogger | 1297
Hádám že hledáš persistentní komponenty.
https://doc.nette.org/…n/components#…
- roman.campula
- Člen | 60
To si nejsem jistý. V dokumentaci se píše, že u perzistentních komponent se „její persistentní parametry přenáší i mezi různými akcemi presenteru nebo mezi více presentery“. To já asi nepotřebuji. Jsem pořád na stejné akci i presenteru. Pouhé přidání
nepomohlo.
- Šaman
- Člen | 2667
Nebude problém v tom, že v kontruktoru nastavuješ natvrdo
questionId
na 1? RedrawControl vytvoří další request na
pozadí, incrementovaná questionId
se v konstruktoru přepíše a
máš tam zase jedničku.
Podle dokumentace od boku (teď jsem nějakou dobu persistentní parametry nepoužíval):
Plus označení komponenty jako perzistentní.
Btw. nejsi stále na stejné akci presenteru (resp. nejsi ve stejném requestu). Po odeslání formuláře dojde k odeslání a novému requestu, ať už viditelně, nebo skrytě ajaxově.
Editoval Šaman (13. 11. 2021 13:56)
- roman.campula
- Člen | 60
Tak dobře, díky za navedení. Každopádně: komponenta je perzistentní
proměnná v komponentě je také perzistentní a v konstruktoru nic není
ve funkci render() je správná hodnota (inkrementovaná o 1)
ale ve funkci createComponentForm() je stále původní hodnota questionId z předchozí otázky/zobrazení
To znamená, že se createComponentForm() zavolá dříve, než je nastavena
proměnná $this->questionId
?
Editoval roman.campula (13. 11. 2021 15:04)
- Martk
- Člen | 661
Spíše to vypadá na nekorektní překreslení. Vše je v životním cyklu. Takže cesta je zjednodušeně taková:
request → vytvoření komponenty → vytvoření formuláře (otázka č.1), protože se musí nejprve zpracovat → událost onSuccess (inkrementace questionId) → žádost o překreslení → začátek vykreslení šablony → vyžádání formuláře (formulář byl už dříve vytvořen, aby byl zpracován, takže pořád bude otázka č.1, takže se nevykoná znova metoda createComponentForm) → tvůj problém.
Kdybys dal namísto redrawControl → redirect('this')
bez ajaxu
tak vše bude fungovat, protože budou 2 requesty.
Editoval Martk (13. 11. 2021 22:01)
- Milo
- Nette Core | 1283
Zhruba jak píše @Martk. Metoda createComponentForm()
se
zavolá pouze jednou a v té nastavíš formuláři současné
questonId
. A zavolá se dost brzy před renderováním, aby
formulář mohl přijmout POST data. Potom se vyvolá onSuccess
callback a ty v něm questionId
inkremetuješ, jenže formulář
se o tom už nedozví. Kdybys teď udělal HTTP redirect,
questionId
po něm bude očekávaně 2. Ale ty ho neuděláš,
takže musíš nějak změnit hodnoty ve formuláři na ty další, aby až se
vykreslí jako HTML do snippetu, zobrazoval už druhou otázku. Zjednodušeně
například:
Pár poznámek:
- formuláře jsou v tomhle trochu extra, protože přenášejí svoje parametry v POST a ne v URL
- persistentní parametr a hidden políčko se duplikují – zvaž, jestli nepoužít pouze jedno
- dělat navazující formuláře správně ajaxově je celkem těžké, třeba aby se vykreslilo něco smysluplného při stisku F5 kdykoliv v průběhu
- roman.campula
- Člen | 60
Díky moc za rady, pomohly, vše funguje a já jsem si rozšířil obzory.
Pro další generace uvádím výsledný funkční kód. Shrnutí: Na stránce je test s otázkami, ke každé několik odpovědí. Po zaznamenání odpovědi a přechodu na další otázku se předchozí odpověď uloží do databáze a přejde se na další otázku. Po poslední se zobrazí vyhodnocení (není součástí kódu, to už je mimo téma).
TestPresenter.php
TestControl.php