Symfony AJAX Auto Complete
Sat, 5 Apr 2008 @ 00:04 / Permalink / by Rob Holmes /
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+'&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+'&select_a_id='+$('select_a_id').value+'&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.