Requirements:

  1. User navigates to path "new-problem" and is presented with a math problem and multiple choice answers, one of which is correct.
  2. There is one submit button per choice
  3. If the user clicks a wrong choice, we record that to the database and the same problem is shown again (user gets another chance)
  4. 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!

share|improve this question

1 Answer

you can check if $form_state['values']['choices'][$i] is set then $form['choices'][$i]['#disabled'] = true;'

share|improve this answer
I'm not trying to disable anything; the form is displaying fine. The problem is with the validation/submission/rebuilding of the form when the user selects an incorrect choice, which is resulting in a new problem (the first time) instead of the same problem. – JD Leonard Aug 8 '12 at 18:56

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.