8 min read

What is a grid?

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.

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.

LEAVE A REPLY

Please enter your comment!
Please enter your name here