0

I'm trying to create a custom search form that uses ajax to perform the actual search and return the located objects as html.

Currently I'm doing something like this:

function example_module_search_form($form, &$form_state) {
   $form['title'] = array( 
     '#type' => 'textfield',
     '#value' => '',
   );
   $form['submit'] = array(
      '#type' => 'submit',
      '#ajax' => array(
        'callback' => 'example_module_search_callback',
        'wrapper' => 'bottom',
        'method' => 'replace',
      ),
      '#value' => t('Submit'),
   );
   return $form;
}

function example_module_search_callback($form, $form_state) {
   $title = $form_state['input']['title'];
   $objects = db_query('SELECT * FROM {node} n WHERE n.type = :type && title = :title', array(':type' => 'object', ':title' => $title))->fetchAll();
   $output = '';
   foreach($objects as $object):
     $output .= '<div style="border:1px solid red; width:200px; height:200px;">'.$object->title.'</div>';
   endforeach;
   return $output;
}

The above works fine the first time I submit the form, but in subsequent requests the $form_state['input']['title'] is always the same?

Can someone point out what I'm doing wrong or perhaps there's a better approach. The reason why I would like to implement my own search form is that the form will have a very large set of controls which values will be used to query the database.

5
  • You should pass $form_state by reference
    – xurshid29
    Aug 30, 2013 at 5:35
  • @xurshid29 only if he plans to write to it. And actually passing $form by reference sometimes makes sense too.
    – Mołot
    Aug 30, 2013 at 7:43
  • I tested modified version of your code with core search module and it works fine.. And There is wrong line in your code I think: '#value' - used by button, hidden, image_button, submit, token, value elements.
    – xurshid29
    Aug 30, 2013 at 8:07
  • There is no "replace" method according to official API docs. It's "replaceWith" that you're looking for. Also, even though it doesn't matter for your case/code, you shouldn't really set #value on a textfield on your form function, you should use #default_value.
    – Beebee
    Aug 30, 2013 at 8:51
  • you should move the code that searches the DB and builds the result into your form function and insert the results into $form
    – Beebee
    Aug 30, 2013 at 9:39

1 Answer 1

1

Usually in Drupal, the ajax callback is business logic free. You should associate your title (ie string) directly in the form, when ajax had run. I use this :

function contact_contact_search_form($form, &$form_state) {

$string = '';

//Retrive the string value
if (isset($form_state['values'])) { // Does ajax ran ?
   $string = $form_state['values']['string'];
}

$form['string'] = array(
  '#type' => 'textfield',
  '#title' => t('Name'),
);

$form['submit'] = array(
  '#type' => 'submit',
  '#ajax' => array(
      'callback' => 'contact_contact_search_ajax',
      'method' => 'replace',
      'effect' => 'none',
  ),
  '#value' => t('Submit'),
);


// Display the result in the form, but should work if the results are outside of your form
$form['table'] = array(
  '#type' => 'item',
  '#prefix' => '<div id="search-table">',
  '#suffix' => '</div>',
  '#markup' => contact_contact_display_searches($string),
);


return $form;
}


function contact_contact_search_ajax(&$form, &$form_state) {


   $commandes[] = ajax_command_replace('#search-table',drupal_render($form['table']));

   return array(
     '#type' => 'ajax',
     '#commands' => $commandes,
   );
}


// Create your table
function contact_contact_display_searches($string) {
// The query
  $query = db_select('node', 'n')
      ->fields('n')
      ->condition('n.title', '%' . db_like($string) . '%', 'LIKE');
      ->range(0, 20)
      ->execute()->fetchAll();

 // Prepare and clean the results
foreach ($results as $result) {
  $rows[$result->nid] = array(
      'type' => check_plain($types[$result->type]->name),
      'title' => l(check_plain($result->title), 'node/' . $result->nid),
      'email' => check_plain($result->field_pers_email_email),
  );
}

// Simple table theming
$out = theme('table', array(
    'header' => array(t('Type de contenu'), t('Intitulé'), t('email')),
    'rows' => $rows,
    'empty' => t('Aucun résultat avec ces critères de recherche')
        )
  );
}
return $out;


}
3
  • Hello. Could you please add some description about how this code is supposed to solve OP's problem? And maybe add come comments in the code, too?
    – Mołot
    Aug 30, 2013 at 7:46
  • I don't quite get this, can you add the code for contact_contact_search_ajax() and contact_contact_display_searches() as well? Aug 31, 2013 at 0:36
  • The code have been added, use the scroll Sep 4, 2013 at 11:19

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.