Náhodně vybrané prvky ve formuláři

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
_enigma
Člen | 17
+
0
-

Ahoj,

potřebuji vytvořit formulář, kde budou testovací otázky z databáze, které se budou náhodně vybírat.
Pokud si z otázek vygeneruji form, všechny radiolisty vyplním, tak po odeslání se mi v dumpu u některých vrací value NULL. Zde na fóru jsem se dočetl něco o tom, že to bude problém sestavení formu po vykreslení a po odeslání, ale moc jsem z toho nebyl moudrý a nebylo uvedeno žádné řešení.

Lze to nějak udělat? Případně prosím o hrubý nástřel, jak to udělat.

Zjednodušený náhled formu:

	protected function createComponentTestForm()
	{

	$form = new UI\Form;

	// vrátí náhodně 4 řádky z DB s otázkou a odpověďmi
    $questions = $this->tests->getTest();

    $container = $form->addContainer('questions');
    foreach ($questions as $question){
        $answers = array(
            1 => $question->answerOne,
            2 => $question->answerTwo,
            3 => $question->answerThree
        );
        $container->addRadioList($question->id, $question->question, $answers);
    }

    $form->addSubmit('submit', 'Results');
    $form->onSuccess[] = callback($this, 'testFormSucceeded');

Debugger::dump($values) po odeslání formu vrací následující:

...
19 => NULL
34 => 3
9  => 1
58 => NULL
...

přitom všechny radiolisty byly vyplněné. Zda se, že u hodnot NULL nesedí id otázek, která byly původně vyplněné. (Nette 2.2.6, PHP 5.4)

Děkuji všem za reakce a nápady.

Šaman
Člen | 2668
+
0
-

Zkus si pro začátek nevytvářet ten formulář náhodně. Asi to opravdu bude tím, že kontrolní mechanismy nedovolí vrátit hodnoty pro pole, která nebyla ve formuláři definovaná. A ten formulář vytváříš dvakrát – poprvé když se má zobrazit, pak ho uživatel vyplní, odešle a pak ti proběhne request, po kterém si musíš ten formulář vytvořit znovu a on si načte pro každé své pole odpovídající hodnoty. Ale ta pole jsou najednou jiná (a tak jejich hodnoty v POSTu neexistují).

Když budeš načítat poprvé i podruhé stejné otázky a tohle bude fungovat, tak pak budeš řešit problém kde uchovávat id otázek. Většinou se to řeší hidden polem. Takže od boku něco takového.

<?php
foreach ($questions as $question){
    $answers = array(
        1 => $question->answerOne,
        2 => $question->answerTwo,
        3 => $question->answerThree
    );
	$container->addHidden('questionId')->setDefaultValue($question->id);
    $container->addRadioList('answer', $question->question, $answers);
}
?>
_enigma
Člen | 17
+
0
-

Ahoj a díky za reakci. To jsem už také zkoušel a to skutečně jde. Jakmile odstraním prvek náhodnosti, tak je to OK. Nicméně bych tam tu náhodnost potřeboval.

Napadlo mě nechat vyjet všechny ID otázek z DB do pole, to zamíchat a pak vybrat jen třeba prvních 5 položek a předávat je do formu. Zkoušel jsem to v actionTest, ale to taky nezafungovalo. Ovšem nejsem si jist jestli to bylo to správné místo.

Šaman
Člen | 2668
+
0
-

Však jsem ti nahhodil řešení. V tom mém kódu si můžeš přenášey id náhodné otázky a pořadí odpovědi, přestože samotný formulář náhodný není. Prostě si to id hodíš do hidden pole a přeneseš ho už bez problémů.

Jan Endel
Člen | 1016
+
0
-

Pozor na znemožnění editace danéhoho hidden políčka s id přímo ve formuláři skrze JS/inspector

_enigma
Člen | 17
+
0
-

Vyzkoušel jsem přes naznačený postup s addHidden a i tak to vrací u některých NULL (myšleno s rand() v modelu).

Aurielle
Člen | 1281
+
0
-

Nevím, jestli by se ti v tomhle případě místo hackování náhodnosti nevyplatilo použít nízkoúrovňový přístup k formulářům.

_enigma
Člen | 17
+
0
-

Díky Aurielle, to funguje.

Takto to generuji v šabloně:

                  {foreach $questions as $question}
                      <p>{$question->question}</p>
                      <p><input type='radio' name='sel[{$question->id}]' value='1'> {$question->answer1}</p>
                      <p><input type='radio' name='sel[{$question->id}]' value='2'> {$question->answer2}</p>
                      <p><input type='radio' name='sel[{$question->id}]' value='3'> {$question->answer3}</p>
                  {/foreach}

… a poté si id otázek už normálně předávám jako perzistentní parametr v presenteru. A jede to :) Ani netušíte, jakou mám radost.

Vlastně děkuji všem, že jsem alespoň trochu více nahlédl pod pokličku formulářu Nette.