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/