Requirements:
- User navigates to path "new-problem" and is presented with a math problem and multiple choice answers, one of which is correct.
- There is one submit button per choice
- If the user clicks a wrong choice, we record that to the database and the same problem is shown again (user gets another chance)
- If the user clicks the right choice, we record that to the database and a new problem is shown.
I haven't been able to coax Drupal to accomplish this thus far. I'm sure the problem involves how the form is/isn't rebuilt. I believe this to be related to Submitting a form rebuilds (expensive) page upon submit
I tried using a validation function and form_set_error()
when the user chose a wrong choice, but the form kept being rebuilt from scratch with a new problem (instead of the same problem). I tried setting $form_state['rebuild'] = TRUE
to no avail.
The code below works except for the first time. When a user navigates to "new-problem", he is shown the form. Upon clicking an incorrect choice's submit button, the "incorrect" status message is shown, but a new problem is shown. Thereafter, clicking an incorrect choice correctly shows the"incorrect" status message and the problem he got wrong.
hook_menu()
function dfm_menu() {
$items['new-problem'] = array(
'page callback' => 'dfm_new_problem_page',
'access callback' => TRUE,
);
return $items;
}
menu callback
function dfm_new_problem_page() {
$node = dfm_get_new_problem(); // Returns a "problem" node
return drupal_get_form('dfm_problem_form', $node);
}
form builder
function dfm_problem_form($form, &$form_state, $node) {
$form['#nid'] = $node->nid;
$form['#correct_choice'] = $node->field_correct_choice[LANGUAGE_NONE][0]['value'];
$problem = $node->field_problem_mathml[LANGUAGE_NONE][0];
$form['problem'] = array(
'#prefix' => '<div class="problem-mathml">',
'#markup' => check_markup($problem['value'], $problem['format']),
'#suffix' => '</div>',
);
$i = 0;
// One submit button per choice
foreach ($node->field_choice_mathml[LANGUAGE_NONE] as $choice) {
$correct = ($i == $form['#correct_choice']); // TRUE if this choice is the correct choice
$form['choices'][$i] = array(
'button' => array(
'#type' => 'submit',
'#value' => t('This one!'),
'#submit' => $correct ? array('dfm_problem_form_submit_correct') : array('dfm_problem_form_submit_incorrect'),
),
'mathml' => array(
'#markup' => check_markup($choice['value'], $choice['format']),
),
);
$i++;
}
return $form;
}
incorrect submission handler
function dfm_problem_form_submit_incorrect($form, &$form_state) {
// Create a new answer node to record the incorrect answer
dfm_record_answer($form['#nid'], $form['#correct_choice']);
drupal_set_message(t('Incorrect'), 'error');
$form_state['rebuild'] = TRUE;
}
correct submission handler
function dfm_problem_form_submit_correct($form, &$form_state) {
// Create a new answer node to record the correct answer
dfm_record_answer($form['#nid'], $form['#correct_choice']);
drupal_set_message(t('You got the last problem right!'));
}
Thanks for your time!