Displaying Data with Grids in Ext JS

Exclusive offer: get 50% off this eBook here
Learning Ext JS 3.2

Learning Ext JS 3.2 — Save 50%

Build dynamic, desktop-style user interfaces for your data-driven web applications using Ext JS

$26.99    $13.50
by Colin Ramsay Shea Frederick Steve 'Cutter' Blades | October 2010 | AJAX Open Source

The grid is, without doubt, one of the most widely-used components of Ext JS. We all have data, and this needs to be presented to the end user in an easy-to-understand manner. The spreadsheet (a.k.a. grid) is the perfect way to do this—the concept has been around for quite a while because it works. Ext JS takes that concept and makes it flexible and downright amazing!

In this article by Shea Frederick, Colin Ramsay, Steve 'Cutter' Blades, and Nigel White, authors of the book Learning Ext JS 3.2, we will be:

  • Using a GridPanel to display structured data in a user-friendly manner
  • Reading data from the server (which provides the data from a database) to display in the grid
        Read more about this book      

(For more resources on Ext JS, see here.)

What is a grid anyway?

Ext JS grids are similar to a spreadsheet; there are two main parts to each spreadsheet:

  • Columns
  • Rows

Displaying Data with Grids in Ext JS

Here our columns are Title, Released, Genre, and Price. Each of the rows contains movies such as The Big Lebowski, Super Troopers, and so on. The rows are really our data; each row in the grid represents a record of data held in a data store.

A GridPanel is databound

Like many Ext JS Components, the GridPanel class is bound to a data store which provides it with the data shown in the user interface. So the first step in creating our GridPanel is creating and loading a store.

The data store in Ext JS gives us a consistent way of reading different data formats such as XML and JSON, and using this data in a consistent way throughout all of the Ext JS widgets. Regardless of whether this data is originally provided in JSON, XML, an array, or even a custom data type of our own, it's all accessed in the same way thanks to the consistency of the data store and how it uses a separate reader class which interprets the raw data.

Instead of using a pre-configured class, we will explicitly define the classes used to define and load a store.

The record definition

We first need to define the fields which a Record contains. A Record is a single row of data and we need to define the field names, which we want to be read into our store. We define the data type for each field, and, if necessary, we define how to convert from the raw data into the field's desired data type.

What we will be creating is a new class. We actually create a constructor which will be used by Ext JS to create records for the store.

As the 'create' method creates a constructor, we reference the resulting function with a capitalized variable name, as per standard CamelCase syntax:

var Movie = Ext.data.Record.create([
'id',
'coverthumb',
'title',
'director',
'runtime',
{name: 'released', type: 'date', dateFormat: 'Y-m-d'},
'genre',
'tagline',
{name: 'price', type: 'float'},
{name: 'available', type: 'bool'}
]);

Each element in the passed array defines a field within the record. If an item is just a string, the string is used as the name of the field, and no data conversion is performed; the field's value will be whatever the Reader object (which we will learn more about soon) finds in the raw data.

If data conversion is required, then a field definition in the form of an object literal instead of a string may contain the following config options:

  • Name: The name by which the field will be referenced.
  • type: The data type in which the raw data item will be converted to when stored in the record. Values may be 'int', 'float', 'string', 'date', or 'bool'.
  • dateFormat: If the type of data to be held in the field is a date type, then we need to specify a format string as used by the Date.parseDate function.

Defining the data type can help to alleviate future problems, instead of having to deal with all string type data defining the data type, and lets us work with actual dates, Boolean values, and numbers. The following is a list of the built in data types:

Field type

Description

Information

string

String data

 

int

Number

Uses JavaScript's parseInt function

float

Floating point number

Uses JavaScript's parseFloat function

boolean

True/False data

 

date

Date data

dateFormat config required to interpret incoming data.

Now that the first step has been completed, and we have a simple Record definition in place, we can move on to the next step of configuring a Reader that is able to understand the raw data.

The Reader

A store may accept raw data in several different formats. Raw data rows may be in the form of a simple array of values, or an object with named properties referencing the values, or even an XML element in which the values are child nodes.

We need to configure a store with a Reader object which knows how to extract data from the raw data that we are dealing with. There are three built in Reader classes in Ext JS.

ArrayReader

The ArrayReader class can create a record from an array of values.

By default, values are read out of the raw array into a record's fields in the order that the fields were declared in the record definition we created. If fields are not declared in the same order that the values occur in the rows, the field's definition may contain a mapping config which specifies the array index from which we retrieve the field's value.

JsonReader

This JSONReader class is the most commonly used, and can create a record from raw JSON by decoding and reading the object's properties.

By default, the field's name is used as the property name from which it takes the field's value. If a different property name is required, the field's definition may contain a mapping config which specifies the name of the property from which to retrieve the field's value.

XmlReader

An XMLReader class can create a record from an XML element by accessing child nodes of the element.

By default, the field's name is used as the XPath mapping (not unlike HTML) from which to take the field's value. If a different mapping is required, the field's definition may contain a mapping config which specifies the mapping from which to retrieve the field's value.

Loading our data store

In our first attempt, we are going to create a grid that uses simple local array data stored in a JavaScript variable. The data we're using below in the movieData variable is taken from a very small movie database of some of my favorite movies.

The data store needs two things: the data itself, and a description of the data—or what could be thought of as the fields. A reader will be used to read the data from the array, and this is where we define the fields of data contained in our array.

The following code should be placed before the Ext JS OnReady function:

var movieData = [
[
1,
"Office Space",
"Mike Judge",
89,
"1999-02-19",
1,
"Work Sucks",
"19.95",
1
],[
3,
"Super Troopers",
"Jay Chandrasekhar",
100,
"2002-02-15",
1,
"Altered State Police",
"14.95",
1
]
//...more rows of data removed for readability...//
];
var store = new Ext.data.Store({
data: movieData, ,
reader: new Ext.data.ArrayReader({idIndex: 0}, Movie)
});

If we view this code in a browser we would not see anything—that's because a data store is just a way of loading and keeping track of our data. The web browser's memory has our data in it. Now we need to configure the grid to display our data to the user.

Displaying structured data with a GridPanel

Displaying data in a grid requires several Ext JS classes to cooperate:

  • A Store: A data store is a client-side analogue of a database table. It encapsulates a set of records, each of which contains a defined set of fields.
  • A Record definition: This defines the fields (or "columns" in database terminology) which make up each record in the Store. Field name and datatype are defined here.
  • A Reader which uses a Record definition to extract field values from a raw data object to create the records for a Store.
  • A ColumnModel which specifies the details of each column, including the column header to display, and the name of the record field to be displayed for each column.
  • A GridPanel: A panel subclass which provides the controller logic to bind the above classes together to generate the grid's user interface.

If we were to display the data just as the store sees it now, we would end up with something like this:

Displaying Data with Grids in Ext JS

Now that is ugly—here's a breakdown of what's happening:

  • The Released date has been type set properly as a date, and interpreted from the string value in our data. It's provided in a native JavaScript date format—luckily Ext JS has ways to make this look pretty.
  • The Price column has been type set as a floating point number. Note that there is no need to specify the decimal precision.
  • The Avail column has been interpreted as an actual Boolean value, even if the raw data was not an actual Boolean value.

As you can see, it's quite useful to specify the type of data that is being read, and apply any special options that are needed so that we don't have to deal with converting data elsewhere in our code.

Before we move on to displaying the data in our grid, we should take a look at how the convert config works, as it can come in quite useful.

Converting data read into the store

If we need to, we can convert data as it comes into the store, massage it, remove any quirky parts, or create new fields all together. This should not be used as a way to change the display of data; that part will be handled elsewhere.

A common task might be to remove possible errors in the data when we load it, making sure it's in a consistent format for later actions. This can be done using a convert function, which is defined in the 'convert' config by providing a function, or reference to a function. In this case we are going to create a new field by using the data from another field and combining it with a few standard strings.

var store = new Ext.data.Store({
data: movieData,
reader: new Ext.data.ArrayReader({id:'id'}, [
'id',
'title',
'director',
{name: 'released', type: 'date', dateFormat: 'Y-m-d'},
'genre',
'tagline',
'price',
'available',
{name:'coverthumb',convert:function(v, rawData){
return 'images/'+rawData[0]+'m.jpg';
}}
])
});

This convert function when used in this manner will create a new field of data that looks like this:

'images/5m.jpg'

We will use this new field of data shortly, so let's get a grid up and running.

Learning Ext JS 3.2 Build dynamic, desktop-style user interfaces for your data-driven web applications using Ext JS
Published: October 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:
        Read more about this book      

(For more resources on Ext JS, see here.)

Displaying the GridPanel

The class that pulls everything together is the GridPanel. This class takes care of placing the data into columns and rows, along with adding column headers, and boxing it all together in a neat little package.

The movie data store we created isn't much good to anybody just sitting in the computer's memory. Let's display it in a grid by creating a simple GridPanel:

  1. Let's add our data store to the following GridPanel code:

    Ext.onReady(function() {…
    var grid = new Ext.grid.GridPanel({
    renderTo: Ext.getBody(),
    frame: true,
    title: 'Movie Database',
    height: 200,
    width: 520,
    store: store,
    colModel: new Ext.grid.ColumnModel({
    defaultSortable: false,
    columns: [
    {header: "Title", dataIndex: 'title'},
    {header: "Director", dataIndex: 'director'},
    {header: "Released", dataIndex: 'released',
    xtype: 'datecolumn'},
    {header: "Genre", dataIndex: 'genre'},
    {header: "Tagline", dataIndex: 'tagline'}
    ]
    })
    });

  2. Bring this page up in a browser, and here's what we will see:

    Displaying Data with Grids in Ext JS

How did that work?

All except two of the config options used here should be familiar to us now because they are inherited from base classes such as the panel.

Believe it or not, there are only two new config options that are really essential to make a GridPanel different from a Panel! They are:

  • store: This references a store object which provides the data displayed in the grid. Any changes to the store are automatically applied to the UI.
  • ColModel: This is a ColumnModel object which defines how the column headers and data cells are to be displayed. It defines a header for each column, and the name of the field to display in that column.

We can almost read through the configuration like a sentence:

Render our grid into the body of the document, frame it, and give it a title of 'Movie Database'. The height will be 200 and the width 520; it will use our 'store' data store and have the columns specified.

This again shows us the benefits of both object-based configuration, and the Ext JS class hierarchy.

The configuration is readable, not a series of parameters whose order must be remembered.

Also, the renderTo frame, title, height, and width options are all inherited from base classes, and are common to all Panel classes. So we will never have to think about these once we have mastered the Panel class.

Defining a grid's column model

The ColumnModel class encapsulates a set of column objects, each of which defines an individual column's characteristics. This is a mirror image of the field definitions in the Record definition which specify how to read in a field's value from a raw data object.

The ColumnModel works at the opposite end of the data flow. It defines which fields from each record to display (you don't have to show them all), and also how the value from each field is to be converted back into string form for display in the UI.

The ColumnModel also maintains defaults to be applied to the columns which it manages, and offers an API to manipulate the columns, and provide information about them.

To define our grid's columns, we configure the ColumnModel with an array of column config objects. Each of the objects within a ColumnModel's columns array defines one column. The most useful options within a column definition are:

  • header: The HTML to display in the header area at the top of the column.
  • dataIndex: The name of the record field—as defined in the Record definition—to display in each cell of the column.
  • xtype: The type of column to create. This is optional, and defaults to a basic column which displays the referenced data field unchanged. But to display a formatted date using the default date format, we can specify 'datecolumn'. There are several other column xtypes described in the API documentation.

So a ColumnModel definition is like this:

new Ext.grid.ColumnModel({
defaultSortable: false,
columns: [
{header: 'Title', dataIndex: 'title'},
{header: 'Director', dataIndex: 'director'},
{header: 'Released', dataIndex: 'released'},
{header: 'Genre', dataIndex: 'genre'},
{header: 'Tagline', dataIndex: 'tagline'}
]
})

This will create grid column headers that look like the following. We have also set the default of sortable for each column to false by using a master config in the Column Model:

Displaying Data with Grids in Ext JS

Here are some other useful config options for each column within the column model:

Option

Description

Usage

renderer

Specifies a function which

returns formatted HTML to

display in a grid cell

Can be used to format the data for this column into your preferred format. Any type of data can be transformed. We will learn about these in the next

few pages.

hidden

Hides the column

Boolean value defining whether or not the column should be displayed.

hideable

Allows the UI to offer

checkboxes to hide/show

the column

If a column must not be hidden (or indeed begins hidden and must not be shown) by the user, set this option to true.

width

Specifies the column width

in pixels

The width of the column. Default is 100 pixels; overflowing content is hidden.

sortable

Specifies whether the

column is sortable

Boolean value specifying whether or not the column can be sorted. Overrides the defaultSortable configuration of the ColumnModel.

There are several built-in column types, all identified by their own unique xtype which provide special formatting capabilities for cell data.

BooleanColumn

Displays the text true or false (or the locale specific equivalents if you include the correct Ext JS locale file) in the column's cells depending on whether the cell's field value is true or false. It can be configured with alternative true/false display values. Example usage:

{
xtype: 'booleancolumn',
header: 'Available',
dataIndex: 'available',
trueText: 'Affirmative',
falseText: 'Negative'
}

DateColumn

This displays the cell's field value as a formatted date. By default, it uses the date format 'm/d/Y', but it can be configured with a format option specifying an alternative format. The value in the column's associated field must be a date object. Example usage:

{
header: "Released",
dataIndex: 'released',
xtype: 'datecolumn',
format: 'M d Y',
width: 70
}

NumberColumn

Displays the cell's field value formatted according to a format string as used in Ext.util.Format.number. The default format string is "0.00". Example usage:

{
header: "Runtime",
dataIndex: 'runtime',
xtype: 'numbercolumn',
format: '0',
width: 70
}

TemplateColumn

Uses an Ext.XTemplate string to produce complex HTML with any fields from within the row's record embedded.

{
header: "Title",
dataIndex: 'title',
xtype: 'templatecolumn',
tpl: '<img src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="{coverthumb}" ' +
'width="50" height="68" align="left">'+
'<b style="font-size:13px;">{title}</b><br>'+
'Director:<i> {director}</i><br>{tagline}'
}

The tokens in the template (tpl) between braces are field names from the store's record. The values are substituted in to create the rendered value. See the API documentation for the Ext.XTemplate class for more information.

ActionColumn

Displays icons in a cell, and may be configurable with a handler function to process clicks on an icon. Example illustrating arguments passed to the handler function:

{
header: 'Delete',
sortable: false,
xtype: 'actioncolumn',
width: 40,
align: 'center',
iconCls: 'delete-movie',
handler: function(grid, rowIndex, colIdex, item, e) {
deleteMovie(grid.getStore().getAt(rowIndex));
}
}

Summary

We have learned a lot in this article about presenting data in a grid. With this new-found knowledge we will be able to organize massive amounts of data into easy-to-understand grids.


Further resources on this subject:


Learning Ext JS 3.2 Build dynamic, desktop-style user interfaces for your data-driven web applications using Ext JS
Published: October 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Colin Ramsay

Colin Ramsay began his web career hacking around ASP websites in a part-time developer job when he was at university. Since then he's been involved with a range of web technologies, which have provided a springboard for the formation of his UK-based web development company, run in tandem with his fledgling writing projects.

Shea Frederick

Shea Frederick began his career in web development before the term 'Web Application' was commonplace. By the late 1990s, he was developing web applications for Tower Records that combined the call center interface with inventory and fulfillment. Since then, Shea has worked as a developer for several companies—building and implementing various commerce solutions, content management systems, and lead tracking programs.

Integrating new technologies to make a better application has been a driving point for Shea's work. He strives to use open source libraries as they are often the launching pad for the most creative technological advances. After stumbling upon a young user interface library called YUI-ext several years ago, Shea contributed to its growth by writing documentation, tutorials, and example code. He has remained an active community member for the modern YUI-ext library—Ext JS. Shea's expertise is drawn from community forum participation, work with the core development team, and his own experience as the architect of several large, Ext JS-based web applications. He currently lives in Baltimore, Maryland with his wife and two dogs and spends time skiing, biking, and watching the Steelers.

Shea is the primary author of the first book published on Ext JS, a book which helps to ease beginners into the Ext JS library. He is also a core developer on the Ext JS project along with writing columns for JSMag and running the local Baltimore/DC JavaScript Meetup. His ramblings can be found on his blog, http://www.vinylfox.com and open source code contributions on Github at http://www.github.com/VinylFox/.

Steve 'Cutter' Blades

Cutter is the Senior Web Developer for Dealerskins, a Nashville, Tennessee based hosting provider that develops websites for the Automobile Dealership market. Cutter began his web career when he began learning HTML 1 while in the US Army and stationed with the National Security Agency. Cutter got into application development as a Corporate Support Specialist for a regional ISP, just prior to becoming the IT Director of Seacrets, a large resort destination on the Eastern Shore of Maryland. Cutter has extensive experience as a server- and client-side developer, with a popular blog dedicated to ColdFusion, Ext JS, and other web development technologies.

Books From Packt


jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide

PHP jQuery Cookbook
PHP jQuery Cookbook

ColdFusion 9 Developer Tutorial
ColdFusion 9 Developer Tutorial

Drupal 7
Drupal 7

Joomla! 1.5 JavaScript jQuery
Joomla! 1.5 JavaScript jQuery

YUI 2.8: Learning the Library
YUI 2.8: Learning the Library

OpenStreetMap
OpenStreetMap

IT Inventory and Resource Management with OCS Inventory NG 1.02
IT Inventory and Resource Management with OCS Inventory NG 1.02


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
4
B
E
S
r
3
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software