10 min read

(For more resources on JavaScript, see here.)

Grid panel

The grid panel is one of the most-used components when developing an application Ext JS 4 provides some great improvements related to this component.

The Ext JS 4 Grid panel renders a different HTML than Ext JS 3 Grid did. Sencha calls this new feature Intelligent Rendering. Ext JS 3 used to create the whole structure, supporting all the features. But, what if someone just wanted to display a simple grid? All the other features not being rendered would just be wasted, because no one was using that structure. Ext JS 4 now renders only the features the grid uses, minimizing and boosting the performance.

Before we examine the grid’s new features and enhancements, let’s take a look how to implement a simple grid in Ext JS 4:

Ext.create('Ext.grid.Panel', { store: Ext.create('Ext.data.ArrayStore', { fields: [ {name: 'book'}, {name: 'author'} ], data: [['Ext JS 4: First Look','Loiane Groner']] }), columns: [ { text : 'Book', flex : 1, sortable : false, dataIndex: 'book' },{ text : 'Author', width : 100, sortable : true, dataIndex: 'author' }], height: 80, width: 300, title: 'Simple Grid', renderTo: Ext.getBody() });

As you can see in the preceding code, the two main parts of the grid are the store and the columns declarations. Note, as well, names of both store and model fields always have to match with the column’s dataIndex (if you want to display the column in the grid).

So far, nothing has changed. The way we used to declare a simple grid in Ext JS 3 is the same way we do for Ext JS 4.

However, there are some changes related to plugins and the new features property. We are going to take a closer look at that in this section.

Let’s dive into the changes!

Columns

Ext JS 4 organizes all the column classes into a single package—the Ext.grid.column package.

We will explain how to use each column type with an example. But first, we need to declare a Model and a Store to represent and load the data:

Ext.define('Book', { extend: 'Ext.data.Model', fields: [ {name: 'book'}, {name: 'topic', type: 'string'}, {name: 'version', type: 'string'}, {name: 'released', type: 'boolean'}, {name: 'releasedDate', type: 'date'}, {name: 'value', type: 'number'} ] }); var store = Ext.create('Ext.data.ArrayStore', { model: 'Book', data: [ ['Ext JS 4: First Look','Ext JS','4',false,null,0], ['Learning Ext JS 3.2','Ext JS','3.2',tr ue,'2010/10/01',40.49], ['Ext JS 3.0 Cookbook','Ext JS','3',true,'2009/10/01',44.99], ['Learning Ext JS','Ext JS','2.x',true,'2008/11/01',35.99], ] });

Now, we need to declare a grid:

Ext.create('Ext.grid.Panel', { store: store, width: 550, title: 'Ext JS Books', renderTo: 'grid-example', selModel: Ext.create('Ext.selection.CheckboxModel'), //1 columns: [ Ext.create('Ext.grid.RowNumberer'), //2 { text: 'Book',//3 flex: 1, dataIndex: 'book' },{ text: 'Category', //4 xtype:'templatecolumn', width: 100, tpl: '{topic} {version}' },{ text: 'Already Released?', //5 xtype: 'booleancolumn', width: 100, dataIndex: 'released', trueText: 'Yes', falseText: 'No' },{ text: 'Released Date', //6 xtype:'datecolumn', width: 100, dataIndex: 'releasedDate', format:'m-Y' },{ text: 'Price', //7 xtype:'numbercolumn', width: 80, dataIndex: 'value', renderer: Ext.util.Format.usMoney },{ xtype:'actioncolumn', //8 width:50, items: [{ icon: 'images/edit.png', tooltip: 'Edit', handler: function(grid, rowIndex, colIndex) { var rec = grid.getStore().getAt(rowIndex); Ext.MessageBox.alert('Edit',rec.get('book')); } },{ icon: 'images/delete.gif', tooltip: 'Delete', handler: function(grid, rowIndex, colIndex) { var rec = grid.getStore().getAt(rowIndex); Ext.MessageBox.alert('Delete',rec.get('book')); } }] }] });

The preceding code outputs the following grid:

  • The first column is declared as selModel, which, in this example, is going to render a checkbox, so we can select some rows from the grid. To add this column into a grid, simply declare the selModel (also known as sm in Ext JS 3) as CheckBox selection model, as highlighted in the code (comment 1 in the code).
  • The second column that we declared is the RowNumberer column. This column adds a row number automatically into the grid.
  • In the third column (with text:’Book’), we did not specify a column type; this means the column will display the data itself as a string.
  • In the fourth column, we declared a column with xtype as templatecolumn. This column will display the data from the store, specified by an XTemplate, as declared in the tpl property. In this example, we are saying we want to display the topic (name of the technology) and its version.
  • The fifth column is declared as booleancolumn. This column displays a true or false value. But, if we do not want to display true or false in the grid, we can specify the values that we want to get displayed. In this example, we displayed the value as Yes (for true values) and No (for false values), as we declared in the trueText and falseText.
  • The sixth column we declared as datecolumn, which is used to display dates. We can also declare a date format we want to be displayed. In this example, we want to display only the month and the year. The format follows the same rules for PHP date formats.
  • The seventh column we declared as numbercolumn. This column is used to display numbers, such as a quantitative number, money, and so on. If we want to display the number in a particular format, we can use one of the Ext JS renderers to create a customized one.
  • And the last column we declared is the actioncolumn. In this column, we can display icons that are going to execute an action, such as delete or edit. We declare the icons we want to display in the items property.
    • topic: {name}{rows.length} Book
    • topic: {name}{rows.length} Books

Feature support

In Ext JS 3, when we wanted to add a new functionality to a grid, we used to create a plugin or extend the GridPanel class. There was no default way to do it. Ext JS 4 introduces the Ext.grid.feature.Feature class that contains common methods and properties to create a plugin.

Inside the Ext.grid.feature packages, we will find seven classes: AbstractSummary, Chunking, Feature, Grouping, GroupingSummary, RowBody, and Summary.

A feature is very simple to use—we need to add the feature inside the feature declaration in the grid:

features: [{ groupHeaderTpl: 'Publisher: {name}', ftype: 'groupingsummary' }]

Let’s take a look at how to use some of these native grid features.

Ext.grid.feature.Grouping

Grouping rows in Ext JS 4 has changed. Now, Grouping is a feature and can be applied to a grid through the features property.

The following code displays a grid grouped by book topic:

Ext.define('Book', { extend: 'Ext.data.Model', fields: ['name', 'topic'] }); var Books = Ext.create('Ext.data.Store', { model: 'Book', groupField: 'topic', data: [{ name: 'Learning Ext JS', topic: 'Ext JS' },{ name: 'Learning Ext JS 3.2', topic: 'Ext JS' },{ name: 'Ext JS 3.0 Cookbook', topic: 'Ext JS' },{ name: 'Expert PHP 5 Tools', topic: 'PHP' },{ name: 'NetBeans IDE 7 Cookbook', topic: 'Java' },{ name: 'iReport 3.7', topic: 'Java' },{ name: 'Python Multimedia', topic: 'Python' },{ name: 'NHibernate 3.0 Cookbook', topic: '.NET' },{ name: 'ASP.NET MVC 2 Cookbook', topic: '.NET' }] }); Ext.create('Ext.grid.Panel', { renderTo: Ext.getBody(), frame: true, store: Books, width: 350, height: 400, title: 'Books', features: [Ext.create('Ext.grid.feature.Grouping',{ groupHeaderTpl: 'topic: {name} ({rows.length} Book{[values.rows.length > 1 ? "s" : ""]})' })], columns: [{ text: 'Name', flex: 1, dataIndex: 'name' },{ text: 'Topic', flex: 1, dataIndex: 'topic' }] });

In the groupHeaderTpl attribute, we declared a template to be displayed in the grouping row. We are going to display one of the following customized strings, depending on the number of books belonging to the topic:

The string comprises of the topic name ({name}) and the count of the book for the topic ({rows.length}).

In Ext JS 3, we still had to declare a grouping field in the store; but, instead of a Grouping feature, we used to declare GroupingView, as follows:

view: new Ext.grid.GroupingView({ forceFit:true, groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Books" : "Book"]})' })

If we execute the grouping grid, we will get the following output:

 

Ext.grid.feature.GroupingSummary

The GroupingSummary feature also groups rows with a field in common, but it also adds a summary row at the bottom of each group.

Let’s change the preceding example to use the GroupingSummary feature:

Ext.create('Ext.grid.Panel', { renderTo: Ext.getBody(), frame: true, store: Books, width: 350, height: 400, title: 'Books', features: [{ groupHeaderTpl: 'Topic: {name}', ftype: 'groupingsummary' }], columns: [{ text: 'Name', flex: 1, dataIndex: 'name', summaryType: 'count', summaryRenderer: function(value){ return Ext.String.format('{0} book{1}', value, value !== 1 ? 's' : ''); } },{ text: 'Topic', flex: 1, dataIndex: 'topic' }] });

We highlighted two pieces in the preceding code. The first line is the feature declaration: in the previous example (Grouping) we created the feature using the Ext.create declaration. But if we do not want to explicitly create the feature every time we declare, we can use the ftype property, which is groupingsummary in this example.

The groupingsummary that we added to the grid’s name column is in the second line of highlighted code. We declared a summaryType property and set its value as count. Declaring the summaryType as count means we want to display the number of books in that particular topic/category; it is going to count how many records we have for a particular category in the grid. It is very similar to the count of the PL/SQL language. Other summary types we can declare are: sum, min, max, average (these are self-explanatory).

In this example, we want to customize the text that will be displayed in the summary, so we are going to use the summaryRenderer function. We need to pass a value argument to it, and the value is the count of the name column. Then, we are going to return a customized string that is going to display the count (token {0}) and the string book or books, depending on the count (if it is more than 1 we add s at the end of the string book).

Ext.String.format is a function that allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each token must be unique and must increment in the format {0}, {1}, and so on.

The preceding code will output the following grid:

Ext.grid.feature.Summary

The GroupingSummary feature adds a row at the bottom of each grouping. The Summary feature adds a row at the bottom of the grid to display summary information. The property configuration is very similar to that for GroupingSummary, because both classes are subclasses of AbstractSummary (a class that provides common properties and methods for summary features).

Ext.create('Ext.grid.Panel', { renderTo: Ext.getBody(), frame: true, store: Books, width: 350, height: 300, title: 'Books', features: [{ ftype: 'summary' }], columns: [{ text: 'Name', flex: 1, dataIndex: 'name', summaryType: 'count', summaryRenderer: function(value){ return Ext.String.format('{0} book{1}', value, value !== 1 ? 's' : ''); } },{ text: 'Topic', flex: 1, dataIndex: 'topic' }] });

The only difference from the GroupingSummary feature is the feature declaration itself. The summayType and summaryRenderer properties work in a similar way. The preceding code will output the following grid:

Ext.grid.feature.RowBody

The rowbody feature adds a new tr->td->div in the bottom of the row that we can use to display additional information.

Here is how to use it:

Ext.create('Ext.grid.Panel', { renderTo: Ext.getBody(), frame: true, store: Books, width: 350, height: 300, title: 'Books', features: [{ ftype: 'rowbody', getAdditionalData: function(data, idx, record, orig) { return { rowBody: Ext.String.format( '

->topic: {0}
', data.topic) }; } }, { ftype: 'rowwrap' }], columns: [{ text: 'Name', flex: 1, dataIndex: 'name' }] });

 

In the preceding code, we are not only displaying the name of the book; we are using the rowbody to display the topic of the book as well.

The first step is to declare the rowbody feature. One very important thing to be noted is that rowbody will be initially hidden, unless you override the getAdditionalData method.

If we execute the preceding code, we will get the following output:

LEAVE A REPLY

Please enter your comment!
Please enter your name here