Apologies for the long subject, don't know how to phrase the question of what I want to do. I am creating a custom form with the code below (unfinished, wanted to get the basics working first). It simply generates a form with two select boxes - one for Monitor Grade, one for paging count and a table showing the results of these choices.

I have gone through the form api and searched on the forums, but cannot find the answer to this question, or at least one I can get to work! I want the submit button to reload the form, with the values of the two select boxes changing the table. ie if the user selects C in Grade to View and 50 in How many to show, the table changes to that information and the select boxes have that as their selected option.

I have absolutely no idea where to go from here. I have tried using a return = 'monitor-model-summary?grade=' ... and that encoded the ? and & so failed. Tried other solutions in various posts and none of them worked.

This is the code so far, after removing all of the trial and error bits that failed:

/* Monitor Model Grade breakdown */

/**
 * Called when user goes to example.com/?q=monitor_summary
 */
function monitor_summary() {
  $output = t('This page summarises the Monitor Model Grade breakdown.');
  $output .= drupal_get_form('monitor_summary_form');
  return $output;
}

/**
 * Creates the Monitor Model/Grade Summary form
 */
function monitor_summary_form() {
  $grade = 'A'; // Want this as default, changing to user choice
  $count = 20; // Want this as default, changing to user choice
  $form['selection'] = array(
    '#title' => t('Filter Selection'),
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#description' => t('Filter the Grades you need to modify.'),
  );
  $form['selection']['grade'] = array(
    '#title' => 'Grade to view',
    '#type' => 'select',
/*    '#multiple' => 'multiple', */
    '#options' => array('A' => 'A', 'B' => 'B', 'C' => 'C', 'F' => 'F', 'Not Graded' => 'Not Graded'),
    '#default_value' => $grade,
  );
  $form['selection']['quantity'] = array(
    '#title' => 'How many to show',
    '#type' => 'select',
/*    '#multiple' => 'multiple', */
    '#options' => array(5 => 5, 10 => 10, 20 => 20, 50 => 50, 75 => 75, 100 => 100, 150 => 150, 200 => 200),
    '#default_value' => $count,
  );
  $form['selection']['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Update',
    '#redirect' => 'monitor-model-summary',
  );
  $form['header'] = array(
    '#type' => 'value',
    '#value' => array(
      array('data' => t('Model ID'), 'field' => 'nid'),
      array('data' => t('Model Name'), 'sort' => 'asc', 'field' => 'title'),
      array('data' => t('Grade'), 'field' => 'grade'),
      array('data' => t('Qty'), 'field' => 'qty'),
    ),
  );
  $sql = "SELECT c.`nid`, n.`title`, c.`grade`, c.`qty` FROM {nrg_custom_monitors} c, {node} n
          WHERE n.`nid` = c.`nid` AND c.`grade`='". $grade ."'". tablesort_sql($form['header']['#value']);
  $results = pager_query($sql, $count);
  while ($row = db_fetch_object($results)) {
    $rows[] = $row;
  }
  foreach ($rows as $v) {
    $form['nid'][$v->nid] = array('#type' => 'markup', '#value' => $v->nid);
    $form['title'][$v->nid] = array('#type' => 'markup', '#value' => $v->title);
    $form['grade'][$v->nid] = array('#type' => 'markup', '#value' => $v->grade);
    $form['qty'][$v->nid] = array('#type' => 'markup', '#value' => $v->qty);
  }
  return $form;
}

function monitor_summary_form_validate($form_id, $form_values) {

}

function monitor_summary_form_submit($form_id, $form_values) {
  drupal_set_message(t('Your form has been updated to show '. $form_values['quantity'] . ' x '. $form_values['grade'] .' Grades.'));
  $form_values['#redirect'] = array($form_values['grade'], $form_values['quantity']);
}

/**
 * Themes the form into a table
 * @param array $form The form to theme
 * @return string
 */
function theme_monitor_summary_form($form) {
  foreach (element_children($form['title']) as $key) {
    $row = array();
    $row[] = drupal_render($form['nid'][$key]);
    $row[] = drupal_render($form['title'][$key]);
    $row[] = drupal_render($form['grade'][$key]);
    $row[] = drupal_render($form['qty'][$key]);
    $rows[] = $row;
  }
  $output = drupal_render($form); // Process any other fields and display them
  $output .= theme('table', $form['header']['#value'], $rows); // Now render the table and display
  return $output . theme('pager', $count);
}

If someone could point me in the right direction or take pity on someone who is feeling incredibly dumb right now and say "It's simple - just do this ...", it would be much appreciated!

Comments

Balefire’s picture

Okay, once again I solve it myself not that long after I post the question! The answer lies in treating the form as a multi-stage, without an ending point. Not 100% certain if this is the correct way, but at least it is finally doing exactly what I wanted it to do at this stage!
Complete code again, easier than picking out the changes:

/**
 * Implementation of hook_menu().
 */
function nrg_custom_forms_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    ...
    $items[] = array(
       'path' => 'monitor-model-summary',
       'title' => t('Monitor Model/Grade Summary'),
       'callback' => 'drupal_get_form',
       'callback_arguments' => array('monitor_summary_form'),
       'type' => MENU_CALLBACK,
       'access' => TRUE
    );
    ...
  }
  return $items;
}

/**
 * Called when user goes to example.com/?q=monitor_summary
 */
function monitor_summary() {
  $output = t('This page shows the Monitor Model to Grade breakdown.');
  $output .= drupal_get_form('monitor_summary_form');
  return $output;
}

/**
 * Creates the Monitor Model/Grade Summary form
 */
function monitor_summary_form($form_values = NULL) {
  $form['#multistep'] = TRUE;
  $form['#redirect'] = FALSE;
  $grade = isset($form_values) ? $form_values['grade'] : 'A'; // First time in? Set default value
  $count = isset($form_values) ? (int) $form_values['count'] : 20; // First time in? Set default value
  $form['selection'] = array(
    '#title' => t('Filter Selection'),
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#description' => t('Filter the Grades you need to modify.'),
  );
  $form['selection']['grade'] = array(
    '#title' => 'Grade to view',
    '#type' => 'select',
/*    '#multiple' => 'multiple', */
    '#options' => array('A' => 'A', 'B' => 'B', 'C' => 'C', 'F' => 'F', 'Not Graded' => 'Not Graded'),
    '#default_value' => $grade,
  );
  $form['selection']['count'] = array(
    '#title' => 'How many to show',
    '#type' => 'select',
/*    '#multiple' => 'multiple', */
    '#options' => array(
      5 => 5,
      10 => 10,
      20 => 20,
      50 => 50,
      75 => 75,
      100 => 100,
      150 => 150,
      200 => 200,
    ),
    '#default_value' => $count,
  );
  $form['selection']['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Update',
    '#redirect' => 'monitor-model-summary',
  );
  $form['header'] = array(
    '#type' => 'value',
    '#value' => array(
      array('data' => t('Model ID'), 'field' => 'nid'),
      array('data' => t('Model Name'), 'sort' => 'asc', 'field' => 'title'),
      array('data' => t('Grade'), 'field' => 'grade'),
      array('data' => t('Qty'), 'field' => 'qty'),
    ),
  );
  $sql = "SELECT c.`nid`, n.`title`, c.`grade`, c.`qty` FROM {nrg_custom_monitors} c, {node} n
          WHERE n.`nid` = c.`nid` AND c.`grade`='". $grade ."'". tablesort_sql($form['header']['#value']);
  $results = pager_query($sql, $count);
  while ($row = db_fetch_object($results)) {
    $rows[] = $row;
  }
  foreach ($rows as $v) {
    $form['nid'][$v->nid] = array('#type' => 'markup', '#value' => $v->nid);
    $form['title'][$v->nid] = array('#type' => 'markup', '#value' => $v->title);
    $form['grade'][$v->nid] = array('#type' => 'markup', '#value' => $v->grade);
    $form['qty'][$v->nid] = array('#type' => 'markup', '#value' => $v->qty);
  }
  return $form;
}

function monitor_summary_form_validate($form_id, $form_values) {
  // Validate the choices, make sure no nasty surprises lurk - i.e SQL injections, etc
}

function monitor_summary_form_submit($form_id, $form_values) {
  // Temporary message to see what is happening with the necessary values. To be removed from final code
  drupal_set_message(t('Your form has been updated to show '. $form_values['count'] . ' x '. $form_values['grade'] .' Grades.'));
  return;
}

/**
 * Themes the form into a table
 * @param array $form The form to theme
 * @return string
 */
function theme_monitor_summary_form($form) {
  foreach (element_children($form['title']) as $key) {
    $row = array();
    $row[] = drupal_render($form['nid'][$key]);
    $row[] = drupal_render($form['title'][$key]);
    $row[] = drupal_render($form['grade'][$key]);
    $row[] = drupal_render($form['qty'][$key]);
    $rows[] = $row;
  }
  $output = drupal_render($form); // Process any other fields and display them
  $output .= theme('table', $form['header']['#value'], $rows); // Now render the table and display
  return $output . theme('pager', $count);
}

Found the answer (after trying so many different "solutions") in Pro Drupal 5 Development which has been on my shelf for months!

Now, how do I mark this thread as closed/fixed?

**Minor Update**
Using the above would reset the page back to default values for $grade & $count when using table paging, so I changed:
$grade = isset($form_values) ? $form_values['grade'] : 'A';
into:

  if (isset($form_values)) {
    $grade = $form_values['grade'];
  }
  elseif (isset($_GET['grade'])) {
    $grade = $_GET['grade'];
  }
  else {
    $grade = 'A';
  }

Repeat for $count. This looks wrong somehow, but can't think of a better way to do it. Also, the menu generation stopped working, so I changed it back to the original:

    $items[] = array(
        'path' => 'monitor-model-summary',
        'title' => t('Monitor Model/Grade Summary'),
        'callback' => 'monitor_summary',
        'access' => TRUE,
    );
czeky’s picture

subscribing