CakePHP - jQuery Autocomplete Tutorial
In this tutorial, i will show you how to implement jQuery UI’s autocomplete widget in cakephp. The script in this tutorial is copy paste from tutorialzine article “A Simple Movie Search App w/ jQuery UI” . We are using a MySql database containing a users table. When you start typing a user name in the text box of the search form, an AJAX request is sent to controller. The controller returns a JSON object with suitable user name.
This is what we’re going to create:
MySQL Table
CREATE TABLE `users` ( `id` int(10) unsigned NOT NULL auto_increment, `username` text, `profile_pictures` varchar(64) default NULL, `created` datetime default NULL, `modified` datetime default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=31 DEFAULT CHARSET=latin1
routes.php
<?php //file:app/config/routes.php Router::connect('/', array('controller' => 'users', 'action' => 'home')); /** * ...and connect the rest of 'Pages' controller's urls. */ Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); ?>
On apps first load, we will redirect the apps to home action in users controller.
default.ctp
<?php //file:app/view/layout/default.ctp ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <?php echo $this->Html->charset(); ?> <title> <?php __('CakePHP: the rapid development php framework:'); ?> <?php echo $title_for_layout; ?> </title> <?php echo $this->Html->meta('icon'); echo $this->Html->css('cake.generic'); echo $scripts_for_layout; ?> </head> <body> <div id="container"> <div id="header"> <h1><?php echo $this->Html->link(__('CakePHP: the rapid development php framework', true), 'http://cakephp.org'); ?></h1> </div> <div id="content"> <?php echo $this->Session->flash(); ?> <?php echo $content_for_layout; ?> </div> <div id="footer"> <?php echo $this->Html->link( $this->Html->image('cake.power.gif', array('alt'=> __('CakePHP: the rapid development php framework', true), 'border' => '0')), 'http://www.cakephp.org/', array('target' => '_blank', 'escape' => false) ); ?> </div> </div> <?php echo $this->element('sql_dump'); ?> <?php echo $javascript->link('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js');?> <?php echo $javascript->link('http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js');?> <?php echo $javascript->link('application.js');?> </body> </html>
In deafult.ctp we are are included jQuery, jQuery UI and our own script “application.js” (will create later).
users_controller.php
<?php //file:app/controller/users_controller.php <?php class UsersController extends AppController { var $name = 'Users'; var $helpers = array('Ajax', 'Javascript'); var $components = array('RequestHandler'); function home(){ } function search(){ if ( $this->RequestHandler->isAjax() ) { Configure::write ( 'debug', 0 ); $this->autoRender=false; $users=$this->User->find('all',array('conditions'=>array('User.username LIKE'=>'%'.$_GET['term'].'%'))); $i=0; foreach($users as $user){ $response[$i]['value']=$user['User']['username']; $response[$i]['label']="<img class=\"avatar\" width=\"24\" height=\"24\" src=".$user['User']['profile_pictures']."/><span class=\"username\">".$user['User']['username']."</span>"; $i++; } echo json_encode($response); }else{ if (!empty($this->data)) { $this->set('users',$this->paginate(array('User.username LIKE'=>'%'.$this->data['User']['username'].'%'))); } } } } ?>
In users_controller.php we need to included ruquestHandler component. The Request Handler component is used in Cake to determine information about the incoming HTTP request. In this tutorial we will used to detect incoming ajax request. We have two action in users_controller home() and search. Home action is used to default page. Search action is action which we will call from our script.
home.ctp
//file:app/views/users/home.ctp <div class="users form"> <?php echo $this->Form->create('User',array('action'=>'search'));?> <?php echo $this->Form->input('username',array('type'=>'text','id'=>'username','label'=>'Search')); ?> <?php echo $this->Form->end(__('Submit', true));?> </div> <p><a href="http://blogfreakz.com/">Read & Download on Blogfreakz</a></p>
application.js
////file:app/webroot/js/application.js $(document).ready(function(){ // Caching the movieName textbox: var username = $('#username'); // Defining a placeholder text: username.defaultText('Search for people'); // Using jQuery UI's autocomplete widget: username.autocomplete({ minLength : 1, source : 'users/search' }); }); // A custom jQuery method for placeholder text: $.fn.defaultText = function(value){ var element = this.eq(0); element.data('defaultText',value); element.focus(function(){ if(element.val() == value){ element.val('').removeClass('defaultText'); } }).blur(function(){ if(element.val() == '' || element.val() == value){ element.addClass('defaultText').val(value); } }); return element.blur(); }
The search terms, that the user has entered into the search box, are available in $_GET['term']. Calling the search() method with these terms.The search method will return JSON object, here is sample response:
[{"value":"Webmestre Jobillico","label":"<img class=\"avatar\" width=\"24\" height=\"24\" src=http:\/\/graph.facebook.com\/100001094382363\/picture\/><span class=\"username\">Webmestre Jobillico<\/span>"},{"value":"Web Panorama","label":"<img class=\"avatar\" width=\"24\" height=\"24\" src=http:\/\/graph.facebook.com\/100001449013053\/picture\/><span class=\"username\">Web Panorama<\/span>"},{"value":"Wynnia Savitrie","label":"<img class=\"avatar\" width=\"24\" height=\"24\" src=http:\/\/graph.facebook.com\/100000881073253\/picture\/><span class=\"username\">Wynnia Savitrie<\/span>"},{"value":"Marsie Wilbourn Holton","label":"<img class=\"avatar\" width=\"24\" height=\"24\" src=http:\/\/graph.facebook.com\/705486368\/picture\/><span class=\"username\">Marsie Wilbourn Holton<\/span>"}]
autocomplete.css
/** //file:app/webroot/css/autocomplete.css **/ /** search container **/ .users{ width:640px; margin:0 auto; min-height:225px; } #content p{ width:640px; margin:0 auto; text-align:center; } #username{ border:1px solid silver; padding:3px 10px; clear:none; width:460px; } .input{ clear:none; float:left; } .submit{ clear:none; float:right; padding:20px 0; } /* Styling the markup generated by the autocomplete jQuery UI widget */ ul.ui-autocomplete{ width:250px; background-color:white; border:1px solid gray; margin-left:3px; margin-top:-4px; font-family:Helvetica, Arial,sans-serif; } ul.ui-autocomplete li{ list-style:none; border-top:1px solid white; border-left:1px solid white; margin:0; } ul.ui-autocomplete li:first-child{ border-top:none; } ul.ui-autocomplete li:last-child{ border-bottom:none; } ul.ui-autocomplete li a{ border:none !important; text-decoration:none !important; padding:2px; display:block; color:black; } ul.ui-autocomplete li img{ margin-right:4px; } ul.ui-autocomplete li span{ } #ui-active-menuitem{ background-color:#efefef; cursor:pointer; }
Wrapping Up
This tutorial showed how to implement autocomplete in cakephp. With jquery UI autocomplete widget, the creation of autocomplete become more easier. Cakephp has requesHandler component that we can used to determine the incoming request. Hope you find this tutorial is useful for you.
9 Comments
dogmatic69
11.25.2010
Way to go on sticking with MVC… especially like your usage of html and echo in the controller.
You are already using the RequestHandler to check if its ajax, so why not move that to beforeFilter and set the layout to ajax, then use Router::parseExtentions(‘ajax’) to pick up the ajax requests and send the request to /users/search.ajax
in /view/users/ajax/search.ctp create the link array properly with HtmlHelper and echo it there.
and then you have $user = find(‘all’) but don’t use it… as you are setting users with $this->paginate(). If the db had 10000 users you would pull them all, and then do another find with limits.
You have also included the Ajax helper which does not seem to be used, $javascript should be referred to as $this->Javascript seeming as thought this is written for 1.3
Poor quality tutorial,
Mufti Ali
11.25.2010
Hi, dogmatic69, Thanks for your feedback, highly appreciated
technology review
11.26.2010
The tutorial on cakephp jquery autocomplete is quite good and it has been very useful for me Thanks for posting
technology review´s last blog ..New Features in Opera 11 Beta
pavanesh
12.25.2010
Hi
am using cakephp 1.3 , but it doesn’t seem to be working for me..Any pointer?
does these script included in default.ctp doesn’t support to cakephp 1.3? OR am i missing something important which has not been mentioned here..?
please suggest..
Thanks
Pavanesh
m16u31
01.03.2011
hi it doesnot work for me too, can you upload the app folder please
thanks
miguel
Gazmend Nrecaj
01.06.2011
Hi,
I found this autocomplete so handy for my search function, thnx a lot !!!
One question: I would like te search nach id , for instance country_id , however i would like to have on my autocomplete name of the country showing.
if I put $response[$i]['value']=$departure['Departure']['id']; it works, but it shows on the field the id , i would like to search by id , but shows on the field the $departure['Departure']['city']
swan black
01.16.2011
doesn’t work for me ,sad!
ravikumar
02.03.2011
it is working for me. i never found such a good one.
i want to use multiple auto fill fields, how can i achieve that?
in that case how/where can i manipulate $_GET['term'].
help me in this would be appreciated.
azir
03.21.2011
hi, can you point me how to implement this on 1.3 (i’m with 1.3.7). 1.3 recommends the use of JsHelper and HtmlHelper as replacement for (Javascript|Ajax)Helper. As most tutorials i found still use (Javascript|Ajax)Helper it would be nice if there are some newer tutorial. or should i switch to older version?
There are no trackbacks to display at this time.