After I have finished reading the Ajax Helper section in the Cookbook I felt unsatisfied - it lacks more complex examples. To understand it better I played a bit with it. Below example is a compilation of my conclusions.
We have two simple models linked with one relation: every User belongs to a City.
The goal is to display all Users in a select box. Every time a user is selected, user’s city appears below the control.
DB tables for this example:
CREATE TABLE IF NOT EXISTS `cities` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ; INSERT INTO `cities` (`id`, `name`) VALUES (1, 'Warsaw'), (2, 'Paris'), (3, 'Lisbon'); CREATE TABLE IF NOT EXISTS `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) NOT NULL, `city_id` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ; INSERT INTO `users` (`id`, `name`, `city_id`) VALUES (1, 'Anna', 1), (2, 'Georges', 2), (3, 'Rui', 3);
First of all, we have to generate every model, view and controller using the cake bake.
Secondly, we have to prepare the view: views/users/index.ctp
<!-- Cake uses Prototype for Ajax operations, so first of all we need to link it to the desired view. --> <?php echo $javascript->link('/js/prototype'); ?> <!-- Create select box. --> <?php echo $form->select('user',$users_list);?> <!-- Create div for Ajax update. Inside this div there is a tiny gif indicating that the update is loading. --> <div id='city'> <img src="/ajax/img/progress.gif" alt="progress" id="progress" style="display:none"> </div> <!-- Ads observer to the select box, when the select box is updated call the function specified by 'url' property. While loading the Ajax update enable visibility of 'indicator'. --> <?php echo $ajax->observeField('user', array( //function called by Ajax 'url' =>'getCity', //id of element to be updated 'update' => 'city', //enable visibility of indicator 'indicator'=>'progress', )); ?>
Then we need to take care about the controller: controllers/user_controller.php. First, we have to add the needed helpers and components:
var $helpers = array('Html', 'Form', 'Javascript','Ajax'); var $components = array('RequestHandler');
…and then we need to prepare data to populate our select box.
function index() { (...) $users_list=$this->User->find('list'); $this->set('users_list', $users_list); }
In the last step for the controller we create a function that handle the Ajax request:
function getCity($id=null){ if(!empty($this->data['user'])){ $user=$this->User->read(null, $this->data['user']); $this->set('city',$user['City']['name']); } else{ $this->set('city'," "); } }
Update: Here I should mention that this view will be also accessible browser window. To avoid it we should check first if the request is really an Ajax request:
function getCity($id=null){ if($this->RequestHandler->isAjax()){ if(!empty($this->data['user'])){ $user=$this->User->read(null, $this->data['user']); $this->set('city',$user['City']['name']); } else{ $this->set('city'," "); } else{ $this->Session->setFlash(__('Invalid request', true)); } }
Finally, we need to create a view for getCity() - views/users/get_city.ctp. This view will be loaded inside the defined tag in the index view.
<?php echo $city; ?>
As a result every time we select a user from the select box the city of the selected user should appear below preceded by a progress indicator.
BTW: nice loading indicators generator: http://www.webscriptlab.com/