hydra12’s blog

Tech Stuff, TCEA, PHP, etc.

ExtJS Datagrid with CakePHP

Filed under: Cake, ExtJS — admin at 10:10 am on Monday, November 26, 2007

Note: I’m in the process of updating this post based on some things I learned here.

To use the extjs datagrid with cake (I’m using 1.2 pre-beta), first you need to download extjs and put it in /webroot/js. I put mine in /webroot/js/ext-1.1/. Now add the following lines to your default layout:

1
2
3
<?php echo $javascript->link('ext-1.1/adapter/ext/ext-base'); ?>
<?php echo $javascript->link('ext-1.1/ext-all-debug'); ?>
<?php echo $javascript->link('myScript'); ?>

Line 1 tells extjs that you are using extjs exclusively. You can also use jquery or yui.
Line 2 loads the extjs library. I used ext-all-debug for development purposes.
Line 3 loads my javascript file. I called it myScript.js and put it in /webroot/js.

Just before the tag, add this line:

1
<link rel='StyleSheet' href='<?php echo $this->base ?>/js/ext-1.1/resources/css/ext-all.css' />

This adds a link to extjs’s css file. This is kind of tricky in cake, since cake expects all css files to be in /webroot/css. You could copy the file there, then just use the html helper to link to the file. I didn’t do that because I want to be able to upgrade my extjs files, and I was afraid I’d forget to copy the new css file.

Put this code in the body of your layout:

1
2
3
<div id="grid-panel">
    <div id="grid-paging" style="border:1px solid #99bbe8;overflow:hidden; width: 665px; height: 00px;"></div>
</div>

Your grid-panel div will hold your datagrid. The grid-paging div will hold the paging bar if you want one (we won’t use it here).

I’m creating a grid to keep track of users, so I made a model called User and a controller called Users. Your Users controller should look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
class UsersController extends AppController {
 
    var $name = 'Users';
    var $helpers = array('Html', 'Form', 'Javascript');
 
    function index()
    {
        //blank index method.  We'll load data with a json call from myScript.js.
    }
 
    function getAllUsers()
    {
        $userArray = array();	//this will hold our data from the database.
        $this->layout = 'Ajax'; //this tells the controller to use the Ajax layout instead of the default layout.
        $count = $this->User->findCount(); //counts the number of records in User.
        $userA = $this->User->findAll(null,'*','last_name ASC'); //gets all the User records and sorts them by last name.
	/*
	 ************** Use this code if you are using cake 1.1.xx *************************
	foreach($userA as $userB)
	{
		$temp = array();
		foreach($userB['User'] as $key=>$value)
		{
			$temp[$key] = $value;
		}
		$userArray[] = $temp;					
	}
	*/
	$userArray = Set::extract($userA, '{n}.User');  // use this code if you are using cake 1.2.xx
	$this->set('users','{"total":'.$count.',"users":'.json_encode($userArray).'}');
    }
 
}
?>

Notice that index is blank. We’ll use index as our default controller, and our javascript will call getAllUsers() to fill our grid with json data. If you have ever debugged a cake array, you’ll notice that

$userA = $this->User->findAll(null,'*','last_name ASC');

will return something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$users = array
(
	0 => array
	(
		'User' => array
		(
			'id' => 1,
			'last_name' => 'Jones',
			'first_name' => 'Paul'
		)
	),
	1 => array
	(
		'User' => array
		(
			'id' => 2,
			'last_name' => 'Smith',
			'first_name' => 'Bill'
		)
	)
)

What we really need is an array that looks more like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$users = array
(
	0 => array
	(
		'id' => 1,
		'last_name' => 'Jones',
		'first_name' => 'Paul'
	),
	1 => array
	(
		'id' => 2,
		'last_name' => 'Smith',
		'first_name' => 'Bill'
	)
)

In cake 1.2, you can use

1
$userArray = Set::extract($userA, '{n}.User');

to extract all the ‘user’ arrays and put them into userArray. If you are not using cake 1.2, you have to use a for loop. I did things this way to start with, and just commented it out when I learned how to use Set::extract.

There are several different ways to take our database info and turn it into json data. I use php5 and have enabled json, so I used this in the controller:

1
$this->set('users','{"total":'.$count.',"users":'.json_encode($userArray).'}');

In the view, put this:

1
<?php echo $users; ?>

You can also do this the cake way (not sure if it works in 1.1). In the controller, put this in place of the above line:

1
2
$this->set('total', $count);
$this->set('users',$userArray);

In the view, put this:

1
<?php echo '{"total":'.$total.', "users":'.$javascript->Object($users).'}'; ?>

This will work with php4 or php5.

Now for the fun stuff. In myScript.js, put the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Ext.onReady(function(){
    /******
     ****** host holds the name of my host computer.  I did this because of restrictions on making remote data requests.  If the 
     ****** host is localhost, things look great from my development machine.  If I try to view my page from another computer,
     ****** though, I get errors and nothing happens.  I set my host to tc-mark-lap (the name of my development computer).  If I 
     ****** view my page with localhost in the url, I get an error.  If I view it with tc-mark-lap, everything works.  This way,
     ****** I can view pages from my laptop or from a remote machine.  I'll have to remember to change this when I deploy to my
     ****** production server, though.  I might be able to set this in my controller or in a config table and use the javascript
     ****** helper to set it at runtime.  I'll have to check on that sometime.
     ******/
    var host = 'tc-mark-lap';
 
    //This is the datastore.  My json data will be loaded remotely, then stored in the datastore.  
    //I used the HttpProxy because I'm accessing data on my local machine
    //In my json reader, I define the fields I should get from my json data (id, last_name, first_name, etc.
    var ds = new Ext.data.Store({	
        proxy: new Ext.data.HttpProxy({url: 'http://'+host+'/ekklesia3/users/getAllUsers'}),  //note that I used host in the url
        reader: new Ext.data.JsonReader({
        root: 'users',
	totalProperty: 'total',
        id: 'id'
        },[ 'id','last_name', 'first_name', 'address1', 'address2', 'city', 'state', 'zip', 'homePhone', 'cellPhone', 'otherPhone', 'birthdate', 'grade', 'school_id', 'school'])
    });  
 
    //This is the column model.  This defines the columns in my datagrid.
    //It also maps each column with the appropriate json data from my database (dataIndex).
    var cm = new Ext.grid.ColumnModel([
        {id: 'grid-paging', header: "ID",dataIndex: 'id', width: 100, hidden: true},
	{header: "Last Name", dataIndex: 'last_name', width: 100},
	{header: "First Name", dataIndex: 'first_name', width: 100},
	{header: "Address1", dataIndex: 'address1', width: 100},
	{header: "Address2", dataIndex: 'address2', width: 100},
	{header: "City", dataIndex: 'city', width: 100},
	{header: "State", dataIndex: 'state', width: 100},
	{header: "Zip", dataIndex: 'zip', width: 100}
    ]);
 
    //Here's where we define our datagrid.  Notice 'grid-paging' - 
    //that's the div in our layout that we want to render the grid to.
    //We also have to specify our dataStore and our columnModel.
    //I have no idea what selModel and enableColLock do :-)
    var grid = new Ext.grid.EditorGrid('grid-paging', {
        ds: ds,
	cm: cm,
	selModel: new Ext.grid.RowSelectionModel({singleSelect:false}),
        enableColLock:false
    });
 
    //This sets a layout for our gridpanel div.  I'll try to do a tutorial on 
    //layouts some other time.
    var layout = Ext.BorderLayout.create({
        center: {
            margins:{left:2,top:3,right:2,bottom:3},
            panels: [new Ext.GridPanel(grid)]
        }
    }, 'grid-panel');
 
    grid.render();  //This renders our grid
    ds.load(); //This loads data from the database into the datastore.
})

The comments should explain everything here. This is more of a “Don’t ask questions, it just works” example, since I’m not quite sure how all the extjs stuff works myself at the moment.

Anyway, we now have a working datagrid. I hope that helps someone :-)
hydra12

21 Comments »

515

Comment by Matheus

December 3, 2007 @ 12:15 pm

Thanks a lot! This was perfect timing as I’ve just discovered the power of Ext and wondered how to implement it with Cake. Much appreciated.

516

Comment by zam3858

December 3, 2007 @ 10:53 pm

thanks a lot! i’m getting started on extjs and pairing it with cakephp as well.

i found the Set::extract($userA, '{n}.User'); expecially helpful.

cheers!

517

Comment by vlad

December 19, 2007 @ 9:32 am

Thank you. This is very helpful. It should probably be added to the bakery as well.

Just a couple of notes…

I could only get this to work with (1.2) if I placed the myScript.js include after the container div. Including the file in the head produced a javascript error as though the div was not available.

Also, I needed to grab the param off the end of URL to pass it to the script. Here’s a simple way to do so, assuming you have a URL like http://host/controller/action/55


function getParam() {

var string=document.location.href;
var getValue=string.split("action/");
var param=getValue[1];

return param;
}

The param will now contain 55

518

Comment by phpcurious

December 26, 2007 @ 11:50 pm

Hi,

Maybe you could also show us some tutorials using ExtJS with JQuery and CakePHP ?
I think that could also be interesting!

519

Comment by pere

December 30, 2007 @ 4:00 pm

Hi,
I have tried your example but i have alway this error:

Ext.grid.EditorGrid is not a constructor

Have anybody any idea about it?

520

Comment by bhushan

December 31, 2007 @ 4:47 am

I have followed all the steps as per tutorial. I have created one view-get_all_users.thtml and written following code inthat file:

Object($users).’}'; ?>

Data is displaying but not in ajax . It’s just displying array of data.Please help.How to create view and which code to be written in that view? and please elaborate settings in default.thtml.

521

Comment by bhushan

December 31, 2007 @ 4:48 am

I have followed all the steps as per tutorial. I have created one view-get_all_users.thtml and written following code inthat file:

Object($users).’}'; ?>

Data is displaying but not in ajax . It’s just displying array of data.Please help.How to create view and which code to be written in that view? and please elaborate settings in default.thtml.

522

Comment by Inma

January 4, 2008 @ 2:50 am

I have the same situation like Bhushan.

Could you help us.

Thanks!

523

Comment by foxmask

January 8, 2008 @ 5:26 am

Hello,
what will be the myScript.js for the extjs 2.0 version ?
kind regards.

524

Comment by foxmask

January 8, 2008 @ 5:29 am

@PERE : i met this error because i use extjs 2.0

so i changed

var grid = new Ext.grid.EditorGrid('grid-paging', {

by

var grid = new Ext.grid.EditorGridPanel('grid-paging', {

525

Comment by admin

January 9, 2008 @ 10:38 am

I’m working on an update for extjs 2.0. I’ll try to have it up soon. I meant to get this done sooner, but I’ve been away from my computer (Christmas break).

hydra12

526

Comment by DjZoNe

January 9, 2008 @ 1:16 pm

Thank you for this tutorial.

527

Comment by admin

January 10, 2008 @ 2:47 pm

OK, the new tutorial is up. It works with ext-2.0, and you can find it here: http://www.ntatd.org/mark/?p=30

@phpcurious - I played around with that once, but things ran VERY slow. Apparently, it was a problem with jquery and has probably been fixed. If I have some time later, I may check into it again.

@pere - foxmask is right. Check out the new tutorial and things should work.

@bhushan and inma - when you call getAllUsers, you should get a json string. When you call index, you should get a datagrid. I’m not sure what the problem is without looking at your code. My best suggestion is to post on cake-php’s google group and let me know the url. I’ll try to help as I can.

@everyone - thanks for the comments, questions, and suggestions. I hope you’ll like the new version of the tutorial.

hydra12

543

Comment by phpcurious

January 15, 2008 @ 5:24 am

actually, i was trying it first time using ExtJS + JQuery before putting it to use in cakephp, but so far, the css is not showing up.

My blog post is here:
Combination of ExtJs and JQuery

615

Comment by trav

April 6, 2008 @ 2:56 pm

How do you handle recursive models?


$users = array
(
0 => array
(
[User] => array
(
'id' => 1,
'plan_id'=> 2,
'last_name' => 'Jones',
'first_name' => 'Paul'
)

[Plan] => array
(
'id' => 2,
'name' => 'Plan B'
)
),
1 => array
(
[User] => array
(
'id' => 1,
'plan_id'=> 3,
'last_name' => 'Jones',
'first_name' => 'Paul'
)

[Plan] => array
(
'id' => 3,
'name' => 'Plan C'
)
)
)

So in the example above, how do you get the ext grid to display the Plan name instead of the plan id? This is the power of cake!

623

Comment by Piece of Cake

June 7, 2008 @ 9:21 am

Hey Mark,
thanks for all your work with the tutorials. Did your grid tutorial and it worked fine.
I just have one question as you seem to know ExtJS better than I do ;) I want to integrate this grid in a card layout (have a treepanel navigation and on click it set’s the active item in the card layout to a variable that contains some content).
Now, how do I include that grid there now. Tried to do it with autoLoad: ‘cakeview with grid-div’, but that just resulted in an empty panel.
Do you have an idea?
Thanks!

626

Comment by Lorelie

October 22, 2008 @ 11:21 pm

to pere:

check your ext version

627

Pingback by Fetching Json Data inside Views « Learning CakePHP

October 23, 2008 @ 7:35 pm

[…] under: Building CakePHP with ExtJS, Idiot’s Guide — ldazo @ 1:34 am I’ve been reading hydra’s and djzone’s blog as a reference for starting a cakephp+extjs application. Their tutorials […]

642

Comment by ace

August 25, 2009 @ 7:06 pm

thank you very maccho!

649

Comment by Farooq

January 22, 2010 @ 12:05 am

Hi I am having problems executing the examaple, Can some one please send working copy of the example files in zip format to m.farooqkhan@yahoo.com so that i can compare what am i doning wrong.

I highly appreciate your support.

Regards

654

Comment by LanaCrane

March 29, 2010 @ 11:11 am

Some specialists argue that personal loans aid a lot of people to live the way they want, because they are able to feel free to buy needed things. Moreover, various banks offer term loan for different classes of people.

RSS feed for comments on this post. TrackBack URI

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>