1

I have a simple select form that I want to use as a "Sort By" handler. When user chooses a different option I want it to change the query and display the new results. E.G. sort by duration ASC or sort by duration DESC.

This is my form:

function mortgage_multi_view_sort_form($form, &$form_state) {
     $form = array();
     $sortOptions = array(
        1 => t('Mortgage Duration: Shortest to Longest'),
        2 => t('Mortgage Duration: Longest to Shortest'),
     );

     $form['mortgage_sort'] = array(
        '#type' => 'select',
        '#title' => t('Sort By'),
        '#options' => $sortOptions,
        '#default_value' => 1,
        '#required' => TRUE,
        '#ajax' => array(
            'event' => 'change',
            'callback' => 'ajax_select_callback',
            //'wrapper' => 'replace_model_div',
            'method' => 'replace',
            //'effect' => 'fade',
        ),
     );

     return $form;
 }

When they change this to Longest to Shortest I want to asynchronously display the mortgages in reverse order. Is this best to do in the callback function?

My callback function (currently):

 function ajax_select_callback($form, &$form_state){
 switch($form['mortgage_sort']){
    case 1:
        $result = db_query('SELECT * FROM {mortgage_database} ORDERBY duration DESC');
        displayMortgages($result);
        break;
    case 2:
        $result = db_query('SELECT * FROM {mortgage_database} ORDERBY duration ASC');
        displayMortgages($result);
        break;
 } 

}

In my displayMortgages() function it just takes the entire query and displays it in a table. How do I get this information to block['content'] from my displayMortgages() now?

1 Answer 1

1

You should do all the logic in the form function. However with your particular issue, I would approach it slightly differently. I would simply return the table HTML from displayMortgages() back to the form and display the table as part of the form. But just simply as a #type=> 'markup'. That way, your sort form and the results are one, and you don't need to worry about firing off another ajax command somewhere else.

So your form code would basically be:

function mortgage_multi_view_sort_form($form, &$form_state) {
  $form = array();

  // Default sort direction
  $sort_dir = 'DESC';

  $sortOptions = array(
    'DESC' => t('Mortgage Duration: Shortest to Longest'),
    'ASC' => t('Mortgage Duration: Longest to Shortest'),
  );

  $form['mortgage_sort'] = array(
    '#type' => 'select',
    '#title' => t('Sort By'),
    '#options' => $sortOptions,
    '#default_value' => 'DESC',
    '#required' => TRUE,
    '#ajax' => array(
      'event' => 'change',
      'callback' => 'ajax_select_callback',
      'wrapper' => 'replace_model_div',
      'method' => 'replace',
      //'effect' => 'fade',
    ),
  );

  // Check if a selection on the form has been made, if so then update the direction
  if (isset($form_state['values']['mortgage_sort'])) {
    $sort_dir = $form_state['values']['mortgage_sort'];
  }

  $result = db_query('SELECT * FROM {mortgage_database} ORDERBY duration '.$sort_dir);

  $form['result'] = array(
    '#markup' => (count($result)) ? displayMortgages($result) : '',
    '#prefix' => '<div id="replace_model_div">',
    '#suffix' => '</div>',
  );

  return $form;
}

And you just need to return the part that's being replaced in your ajax callback:

function ajax_select_callback($form, &$form_state) {
  // Just a return of result is sufficient since it's being replaced
  return $form['result'];
}
8
  • Oh my god that makes so much more sense. I was soooo close to an answer. I was hellbent on making the "table" it's own block and printing it but just using it all in the sort_form block and using AJAX to div replace works the same exact way but is cleaner/quicker. Say I was adding more select options like sorting by "amount" or something, would you recommend a switch/case in the hook_form and have my differing queries listed in there?
    – Exziled
    Commented Sep 17, 2015 at 14:52
  • @Exziled Yes, you can perform the query in your form builder, but I would just add a new variable $sort_field and implement the same logic as $sort_dir and you can replace ORDERBY duration with ORDERBY '.$sort_field.'
    – Beebee
    Commented Sep 17, 2015 at 15:09
  • @Exziled there is a way to do it without having it all in the form though using Ajax Commands, particularly the ajax_command_replace. Read how to use commands here
    – Beebee
    Commented Sep 17, 2015 at 16:07
  • I'll take a look at the ajax_command_replace and see what I can figure out! I definitely want to aim to do this best practice to eliminate fixes later. It's great practice :D
    – Exziled
    Commented Sep 17, 2015 at 16:46
  • one last question! If I have another AJAX form on my page such as "filter mortgages" could I essentially use the same callback and $form['result'] with the #markup for it? It'll still replace the same content? I figured it's worth a shot at asking before I spend a few hours doing it xD
    – Exziled
    Commented Sep 17, 2015 at 17:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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