A JavaScript autocomplete element that links through to your database isn’t built into CakePHP any more – here is a simple solution to add to your application using a jQuery plugin.
Why a plugin? jQuery doesn’t include this functionality, it is provided by jQuery UI but including that library may be a heavyweight solution for your application.
It should end up looking like the image below – as you type, relevant options from your database will appear in the list beneath.
You can download the jQuery autocomplete plugin from https://github.com/dyve/jquery-autocomplete
Extract the files from the archive and move the .css and .js files from the src folder into the css and js folders of the CakePHP webroot directory.
Link to the CSS and JavaScript in your default layout:
echo $this->Html->css('jquery.autocomplete');
echo $this->Html->script('jquery.autocomplete.min.js');
Add a small form to your View, in this example there is a model called company and we want to use autocomplete on the name field.
Form->create('Company', array('type' => 'post', 'action' => 'find'));
echo $this->Form->input('name');
echo $this->Form->submit();
echo $this->Form->end();
?>
Add this script block to the bottom of the document which activates the plugin and tells it where to submit AJAX requests to:
Modify jQuery.autocomplete.css to look nice with CakePHP default CSS:
.acResults ul li {
margin: 0px;
padding: 2px 5px;
cursor: pointer;
display: block;
font: menu;
overflow: hidden;
color: #333;
}
Now back to some CakePHP – Your Controller needs a new action which the AJAX requests will be sending data to:
public function find() {
$this->Company->recursive = -1;
if ($this->request->is('ajax')) {
$this->autoRender = false;
$results = $this->Company->find('all', array(
'fields' => array('Company.name'),
//remove the leading '%' if you want to restrict the matches more
'conditions' => array('Company.name LIKE ' => '%' . $this->request->query['q'] . '%')
));
foreach($results as $result) {
echo $result['Company']['name'] . "\n";
}
} else {
//if the form wasn't submitted with JavaScript
//set a session variable with the search term in and redirect to index page
$this->Session->write('companyName',$this->request->data['Company']['name']);
$this->redirect(array('action' => 'index'));
}
}
And finally add some code to the index action in the index action, which handles what happens if the form was submitted via a button press rather than AJAX.
//if there's a session with some data in, add a filter to the search conditions
if ($this->Session->check('companyName')) {
$name = $this->Session->read('companyName');
if ($name) {
$this->paginate['conditions'][] = array('Company.name LIKE' => '%' . $name . '%');
$this->request->data['Company']['name'] = $name;
}
}
That’s it.
To to make submit buttons appear alongside form elements
here is a simple bit of jQuery to improve the appearance
$(document).ready(function(){
$('div.input, div.submit').css({
'float' : 'left',
width : '200px',
clear : 'none'
});
$('div.submit').css('margin-top', '14px');
$('div.input.text').css('margin-top', '-4px');
});
Thanks to the answer on this question from StackOverflow for some inspiration
http://stackoverflow.com/questions/6071828/autocomplete-search-form-cakephp