Creating an Ext JS grid using the Zend Framework

来源:互联网 发布:淘宝刷客怎么判刑2016 编辑:程序博客网 时间:2024/06/04 23:21

 

Web development has become a lot easier with the rise of frameworks and libraries that help you with common tasks. On the server side there’s PEAR, CakePHP, Symfony and the Zend Framework, amongst others. For the client you can choose from YUI, Prototype, Scriptaculous, Ext JS and many, many more. All these libraries and frameworks have some kind of philosophy behind them, and look at things slightly differently. There is no “best” framework, they all have their pros and cons. Today I’m going to use two of the ones I like and create a nice little grid. Take a look at the demo to see the end result.

The grid component from ExtJS looks difficult, the first time you look at it. There are many things you can configure, and they’re not all documented that well. Trying to keep in line with previous entries on naneau.nl, I’m going to use the grid to display a number of blog posts. I’ve based much of the javascript code on the paging example you can find in the Ext JS documentation.

The basis of an Ext JS Grid is data, of course. It stores it’s data in a Store. There are a few ways of getting data into the store. There’s a memory reader, which I have used in a previous post. Today I’m going to be using a HttpProxy to access my data, which the server will return in JSON format.

var ds = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: ‘http://localhost/index/list/’
//change this!
}),

 

reader: new Ext.data.JsonReader({
root: ‘posts’,
totalProperty: ‘count’,
id: ‘id’
}, [
{name: 'title', mapping: 'title'},
{name: 'timestamp', mapping: 'timestamp', type: 'date', dateFormat: 'timestamp'},
{name: 'contents', mapping: 'contents'}
]),

remoteSort: true
});
ds.setDefaultSort(‘timestamp’, ‘desc’);

Notice how I’ve turned on remote sorting, and set a default sort. We will come back to that later, in the controller that will give us our data. The next thing Ext JS wants is something it calls a ‘Column Model’. Basically it’s a set of columns that the grid should contain. You can specify functions that it uses to render the contents of the cells of a specific column, so you can make data look nicer.

function renderDate(value, p, r){
return String.format(‘{0}’, value.dateFormat(‘M j, Y, g:i a’));
}

 

function renderPost(value, p, record) {
var post = record.data['contents'].replace(/(<([^>]+)>)/ig,“”);
//strip html

if (post.length > 200) {
post = post.substr(0,200) + ‘ [...]‘;
//shorten it
}

return String.format(‘<p><b>{0}</b><br />{1}</p>’, value, post);
}

var cm = new Ext.grid.ColumnModel([{
header: "Post",
dataIndex: 'title',
width: 530,
renderer: renderPost,
css: 'white-space:normal;'
},{
header: "Date",
dataIndex: 'timestamp',
width: 150,
renderer: renderDate
}]);

cm.defaultSortable = true;

As you can see I have written two little functions to display two kinds of cells. The post has a title in bold, and a substring of it’s contents below it. The date in unix timestamp format will be parsed into something humans can read using dateFormat(). By making defaultSortable true, all the columns can be sorted by default, which is one of the nicest features of the Ext JS Grid, in my opinion.

The actual grid is now easy to create:

var grid = new Ext.grid.Grid(‘grid-example’, {
ds: ds,
cm: cm,
selModel: new Ext.grid.RowSelectionModel({singleSelect:true}),
enableColLock:false,
loadMask: true
}).render();
//the grid itself

 

var gridFoot = grid.getView().getFooterPanel(true);
var paging = new Ext.PagingToolbar(gridFoot, ds, {
pageSize: 10,
displayInfo: true,
displayMsg: ‘Displaying posts {0} – {1} of {2}’,
emptyMsg: ‘No posts to display’
});
//create a paging footer

ds.load({params:{start:0, limit:10}});
//start loading data from the server

There should be a matching container in your HTML somewhere, with an id “grid-example”, this will be the container for the grid. You should give this a width and height, and hide it’s overflow.

#grid-example {
width:700px;
height:300px;
overflow:hidden;
}

That’s all for the client side. For those of you that come from a PHP background this may seem difficult, while it’s really not. But just in case it’s too scary for you, I’m only going to be looking at juicy php scripts from now on. The HttpProxy from Ext JS will do a request every time it needs data for it’s grid. With it it will send a http post string like:

start=10&limit=10&sort=title&dir=ASC

We can use the variables from that string to create a simple controller action:

public function listAction() {
$offset = (isset($_POST['start'])) ? $_POST['start'] : 0;
$limit = (isset($_POST['limit'])) ? $_POST['limit'] : 10;
$sort = (isset($_POST['sort'])) ? $_POST['sort'] : ‘id’;
$dir = (isset($_POST['dir'])) ? $_POST['dir'] : ‘ASC’;
//request data, do some kind of validation on this

 

Zend_Loader::loadClass(‘Post’);
$pM = new Post();
//post model

$return = array();
//return array
$return['posts'] = $pM->fetchAll(null, array($sort . ‘ ‘ . $dir), $limit, $offset)->toArray();
//the posts
$return['count'] = $pM->getAdapter()->fetchOne(‘SELECT count(*) FROM post’);
//total number of posts

Zend_Loader::loadClass(‘Zend_Json’);
$json = Zend_Json::encode($return);
//result encoded in JSON

$this->getResponse()->setHeader(‘Content-Type’, ‘text/javascript’);
$this->getResponse()->setBody($json);
//encode result and pass it back
}

The Post class I use in this example extends Zend_Db_Table. The only thing you have to remember is that the grid expects both a ‘posts’ bit in the return array and a ‘count’ bit. This corresponds with the JSON reader from the data store:

reader: new Ext.data.JsonReader({
root: ‘posts’,
totalProperty: ‘count’,
id: ‘id’
}

That wasn’t too hard, was it? And the result is just… beautiful! You can of course view the complete JavaScript used.

原创粉丝点击