ExtJS has a lot of components to rapidly develop powerful web applications.
A few days back, I was faced with the need to display hierarchical data extracted from a database. I looked at several alternatives, but none of them was so full-featured and well-integrated as ExtJS is. So I developed a prototype to learn the basics of ExtJS 4 TreeGrid component.

The HTML page loads ExtJS library (I opted to load the full package to avoid dependency issues) and then loads my test application.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>TreeGrid Example</title>
        <link rel="stylesheet" href="ext-4.0.7-gpl/resources/css/ext-all.css" type="text/css">
        <script src="ext-4.0.7-gpl/ext-all.js" type="text/javascript"></script>
        <script src="treegrid.js" type="text/javascript"></script>
    </head>
    <body>
        <h1>TreeGrid Sample</h1>
        <div id="treegrid"></div>
    </body>
</html>

The application code is divided in three parts: widget, data-store and data-model (from bottom to top in the sample code).

/** treegrid.js **/
Ext.onReady(function() {
    // Data model
    Ext.define('Balance', {
        extend: 'Ext.data.Model',
        fields: [
            {name: 'item', type: 'string'},
            {name: 'exp',  type: 'string', sortType: 'asFloat'},
            {name: 'inc',  type: 'string', sortType: 'asFloat'}
        ]
    });

    // Data store
    var store = Ext.create('Ext.data.TreeStore', {
        model: 'Balance',
        proxy: {
            type: 'ajax',
            url: 'treegrid.php'
        },
        folderSort: true,
        autoLoad: false
    });

    // Widget
    var tree = Ext.create('Ext.tree.Panel', {
        title: 'Balance',
        width: 600,
        height: 200,
        resizable: true,
        renderTo: Ext.getBody(),            // Append to body
//        renderTo: Ext.getDom('treegrid'), // Render inside specific element
        useArrows: true,
        rootVisible: false,
        store: store,
//        singleExpand: true, // Expand one branch at a time
        columns: [{
            xtype: 'treecolumn',
            dataIndex: 'item',
            text: 'Item',
            sortable: true,
            flex: 2
        },{
            dataIndex: 'exp',
            text: 'Expenses',
            sortable: true,
            flex: 1
        },{
            dataIndex: 'inc',
            text: 'Income',
            sortable: true,
            flex: 1
        }]
    });
});

The widget definition contains various parameters “visual” parameters (title, width, height, etc.) and an entire section devoted to associate displayed columns to incoming data.

The widget gets its data from a data-store (store: store). The data-store, in turn, gets records from the server (url: ‘treegrid.php’) in JSON format (type: ‘ajax’). The format for the incoming data is defined in the data-model (model: ‘Balance’)

The data-model defines the names and types of the input data and matches the fields defined in the PHP file.

/** treegrid.php **/
$children = array();
$children['root'] = array(); // Root folder
$children['root'][] = array(
    'item' => 'Software',  // Data values
    'exp'  => 150,         //   "    "
    'inc'  => 185,         //   "    "
    'iconCls'  => 'task-folder', // Style
    'expanded' => false,         // Expanded
    'leaf'     => false,         // Leaf
    'id'       => 'soft_1'       // Unique ID
);
$children['root'][] = array(
    'item' => 'Hardware',
    'exp'  => 80,
    'inc'  => 130,
    'iconCls'  => 'task',
    'expanded' => false,
    'leaf'     => true,
    'id'       => 'hard_1');

$children['soft_1'] = array(); // Software folder
$children['soft_1'][] = array(
    'item' => 'Development',
    'exp'  => 100,
    'inc'  => 125,
    'iconCls'  => 'task',
    'expanded' => false,
    'leaf'     => true,
    'id'       => 'soft_1a');
$children['soft_1'][] = array(
    'item' => 'Maintenance',
    'exp'  => 50,
    'inc'  => 65,
    'iconCls'  => 'task',
    'expanded' => false,
    'leaf'     => true,
    'id'       => 'soft_1b');

$id = $_GET['node'];
$data = array(
    'text' => '.',
    'children' => $children[$id]);
echo json_encode($data);

Records generated from the PHP file contains also additional information to guide the display of the treegrid. Key point here is the id field, so that each node is uniquely identified and can be loaded on demand.

Key points in this sample app are:

  • autoLoad: false

    in the JS data-store, to load data only when folders are expanded

  • epanded => false

    in PHP-generated data, so that all folder are not expanded when loaded for the first time