AJAX Auto Complete

I recently came across the problem of using multiple input_auto_complete_tag’s. The problem was I needed to store the ID of my first category somewhere, so I could filter the sub-categories returned in the second input_auto_complete_tag. Also, just to make things a little more complicated, there is a third input_auto_complete_tag that needs results filtered by the previous IDs.

Follow me, as I take you through a quick tutorial of how I did it:

Form Template:

Firstly we need create our form with the three auto completing inputs. To enable us to store the IDs that are returned we’ll put in a hidden tag for each input tag. Also to enable us to get the ID of the selected result, we’ll need a tiny bit of Javascript which runs after selecting the result.

/apps/app/modules/module/templates/formSuccess.php

<?php use_helper('Javascript'); ?>
<p><?php
  // SELECT A
  echo
    input_hidden_tag('select_a_id', '').
    input_auto_complete_tag(
      'select_a',
      '',
      'module/autoComplete?select=a',
      array('autocomplete' => 'off'),
      array(
        'use_style'             => true,
        'after_update_element'  => "function (inputField, selectedItem) { $('select_a_id').value = selectedItem.id; }"
      )
    );
?></p>
<p><?php
  // SELECT B
  echo
    input_hidden_tag('select_b_id', '').
    input_auto_complete_tag(
      'select_b',
      '',
      'module/autoComplete?select=b',
      array('autocomplete' => 'off'),
      array(
        'use_style'             => true,
        'after_update_element'  => "function (inputField, selectedItem) { $('select_b_id').value = selectedItem.id; }",
        'with'                  => " value+'&amp;select_a_id='+$('select_a_id').value"
      )
    );
?></p>
<p><?php
  // SELECT C
  echo
    input_hidden_tag('select_c_id', '').
    input_auto_complete_tag(
      'select_c',
      '',
      'module/autoComplete?select=c',
      array('autocomplete' => 'off'),
      array(
        'use_style'             => true,
        'after_update_element'  => "function (inputField, selectedItem) { $('select_c_id').value = selectedItem.id; }",
        'with'                  => " value+'&amp;select_a_id='+$('select_a_id').value+'&amp;select_b_id='+$('select_b_id').value"
      )
    );
?></p>

The ‘after_update_element’ simply takes the ID from the element we’ve clicked on, in the results of the auto complete function and places it into the hidden tag.

Select B and Select C use the ‘with’ argument to send the ID of the previous selects to our auto complete function (module/autoComplete) enabling us to filter the results we’ll display in the input_auto_complete_tag.

Auto Complete Function:

The auto complete function will be called everytime we’re typing into one of the input_auto_complete_tag’s. As you can see in the code above, we’re also passing through a parameter (eg. module/autoComplete?select=a) specifying which input is calling the function.

/apps/app/modules/module/actions/actions.class.php

<?php
  public function executeAutoComplete()
  {
    // Get which input called the function
    $input = $this->getRequestParameter('select');
    // Get what the user has typed
    $typed = $this->getRequestParameter('select_'.$input);
 
    // Depending what input called this generate $db_results for the template
    switch ( $input )
    {
      case 'a':
 
        //... generate $db_results
 
        break;
 
      case 'b':
        // Get the IDs of previous inputs
        $a_id = $this->getRequestParameter('select_a_id');
 
        //... generate $db_results using $a_id to filter results
 
        break;
 
      case 'c':
        // Get the IDs of previous inputs
        $a_id = $this->getRequestParameter('select_a_id');
        $b_id = $this->getRequestParameter('select_b_id');
 
        //... generate $db_results using $a_id and $b_id to filter results
 
        break;
    }
 
    // Create array with the ID and Name
    $results = array();
    foreach ( $db_results as $row )
    {
      $results[ $row->getId() ] = $row->getName();
    }
 
    // Pass results to the template
    $this->results = $results;
  }
?>

I’ll leave you to generate the database results, as this is very specific to your database model. Although as a hint, it’s usually best to use an LIKE query:

$criteria->add( YourTablePeer::NAME, $typed.'%', Criteria::LIKE );

Auto Complete Template:

/apps/app/modules/module/templates/autoCompleteSuccess.php

  <ul>
    <?php foreach ( $results as $key => $value ): ?>
      <li id="<?php echo $key ?>"><?php echo $value ?></li>
    <?php endforeach; ?>
  </ul>

The auto complete template simply returns a unordered list which will be displayed on our form for the user to select from.

It’s really as easy as that, but if you’ve got any questions or queries about how to get it working for you, please leave a comment and I’ll try and help you out.

Written by Rob | Posted on April 4th, 2008 in symfony |

4 Comments to “AJAX Auto Complete”

  1. Josh says:

    Thanks alot for this, I’m sure it’ll come in use for my project i’m currently working on :D.

  2. Andrzej says:

    hi
    I have I problem with auto complete. I have to pass to autocomplete action value of a radiobutton. My problem is whenever I pass a value of radiobutton I’m loosing value of input box and vice versa. I use something like this:
    ‘off’),
    array(’use_style’ => true, ‘with’ => “‘&radio=’ + $(’radio’).checked”)
    )?>
    Do you have an idea what seems to be a problem?

  3. Andrzej says:

    sorry, don’t know how to past the code in here…

  4. Rob (the author) says:

    Hi Andrzej,

    I think you need to make a slight change to your options array like the following:

    array(’use_style’ => true, ‘with’ => ” value+’&radio=’+$(’radio’).checked”)

    Take note of the value+ before your radio value bit. Please let me know how you get on with this.

    Thanks,

    Rob
    Symfony-Blog.co.uk

Leave a Reply