Monday, August 31, 2009

CakePHP 1.2 – Introduction to Ajax

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.

a

b

BTW: nice loading indicators generator: http://www.webscriptlab.com/

Monday, August 24, 2009

WOW !! I got Google Wave sandbox account.

… and you cannot imagine how I’m happy with this fact.

Bez nazwy

From the beginning it was a bit hard to discover how to really use it. I went back to the movie from Google IO and start repeat what they do in the movie and play a little bit with this. I really start appreciating the new way of communications.

As far I’ve tested it, the core functionality works already fine. Anyway, some features didn’t work for me at all. For example Insert Search Map function used the way it was shown in the movie displays always Australia. (what, in fact, is not so big surprise for me ;)). It freeze also many times .

The first excitement and the real challenge will be to create my first gadget, which is basically my goal. But that must be postponed since the main app is not ready yet.

What are my doubts about it is that it may be difficult to use for a “not-computer” people. I mean the whole idea is completely new, and is great, but it is also difficult to compare to anything else and it may be difficult to understand, especially beyond the basic functionality. And a big part of the power of Google Wave lies in extensions that, at this moment, are far to tricky to use.

However, the real value of Google Wave is a team work/communications which is difficult to discover without “a team” and my contact list remain empty (not to mention 3 robots which I played with) That’s why I wish to invite everyone who has a wave account, want to test it and has the same problem. Please, let me know by sending a comment here or e-mail. And I have to return to the cake…