12
Mar
11

ExtJS GridPanel RowExpander With Ajax Call


This page describes the process of creating an extJS grid panel where each row can be expanded to reveal additional information. The additional information will be retrieved using Ext.Ajax.request.

Requirements

  • Text Editor
  • HTML Web Server

Procedure

There are 2 techniques to get the data:

  1. Load the complete set of data initially and have the row expander simply display it. This is explained in Part I
  2. Allow for lazy loading of the the data when the row is expanded by making an Ajax request. This is explained in Part II

The advantage of the first method is that there is almost zero delay expanding the rows since the data is retrieved ahead of time. The disadvantage is that most of the data that is downloaded may never be displayed

In the second method only the necessary data is retrieved from the server at the cost of the extra time required to make the additional request for data. You will note that things start changing from line 20 to line 50. The remaining code is the same as above.

Part I

Navigate to an empty directory and create the following file.

index.html

<html>
<head>

<link rel="stylesheet" type="text/css"
    href="http://dev.sencha.com/deploy/ext-3.3.1/resources/css/ext-all.css"/>

<script type="text/javascript"
    src="http://dev.sencha.com/deploy/ext-3.3.1/adapter/ext/ext-base-debug.js">
</script>
<script type="text/javascript"
    src="http://dev.sencha.com/deploy/ext-3.3.1/ext-all-debug.js">
</script>
    <script type="text/javascript" src="http://dev.sencha.com/deploy/ext-3.3.1/examples/ux/RowExpander.js"></script>


<script type="text/javascript">

function buildWindow() {
var myColumns = [];


// row expander
var expander = new Ext.ux.grid.RowExpander({
    tpl : new Ext.Template(
        '<p>&nbsp;&nbsp;<b>Age:</b> {age}</p><br>'
    )
});

var myStore = new Ext.data.JsonStore({
	url: 'response2.do',
	autoLoad : false, // we will manually call the load function.
	listeners: {
		'load' : function () {
			myStore.each(function(r) {
				myColumns.push(expander);
				// Full Name			
				var this_column = {};		
				r.fields.each(function(currentField) { 
					if(currentField.name == 'fullName') {
						this_column['header'] = 'Full Name';
						this_column['sortable'] = true;
						this_column['dataIndex'] = 'fullName';
						myColumns.push(this_column); 
						return false; // used as a break statement
					}
				});

				// State
				this_column = {};		
				r.fields.each(function(currentField) { 				
					// Ext.grid.Column API docs has complete attribute list.
					if(currentField.name == 'state') {
						this_column['header'] = 'State';
						this_column['sortable'] = true;
						this_column['dataIndex'] = 'state';
						myColumns.push(this_column); 
						return false; // used as a break statement
					}
				});
																	
				return false; // used as a break statement			
			});
			
		}
	}            
});

var grid = new Ext.grid.GridPanel({
	title : 'Name State Grid',
	store : myStore,
	autoHeight : true,
	plugins: expander,
	cm : new Ext.grid.ColumnModel({}), // Empty columnModel initially.
	renderTo : Ext.getBody()
});

// load the data and perform a reconfigure in the callback.
myStore.load({ 
	callback : function(r, options, success) { 
		var myColumnModel = new Ext.grid.ColumnModel({
			columns : myColumns
		});
		grid.reconfigure(myStore, myColumnModel);			
	}
});

}
Ext.onReady(buildWindow);
</script>
 
</head>
<body>
</body>
</html>

Data for Part I

The following data is provided to the component in Part I of this page. It returns all the information necessary to display the row including the data for the expanded state.

response2.do

{ 
"totalCount" : "4",
"records" : [
    {"state":"NY","fullName":"Ted Williams", "age" : 25},
    {"state":"NJ","fullName":"Bob Smith", "age" : 37},
    {"state":"NY","fullName":"John Adams", "age" : 44},
    {"state":"CA","fullName":"John Doe", "age" : 47}
],
"metaData" : {
	"totalProperty" : 'totalCount',
	"root" : 'records',
	"fields" : ['state', 'fullName', 'age']	
}
}

Part II

This part explains how to take the above grid and make it retrieve additional data once the row is expanded.

Steps:

  1. The first step was to create a blank expander. Unlike the example above the expander will be filled with data on the “beforeexpand” event.
  2. An event listener defined on the “beforeexpand” event makes an Ajax request. The URL for the request is customized based on the row that was clicked on.
  3. The data is decoded and the body of the row is overwritten using a Ext.layout.Template

The highlighted lines below are the ones that have been changed.

index2.html

<html>
<head>

<link rel="stylesheet" type="text/css"
    href="http://dev.sencha.com/deploy/ext-3.3.1/resources/css/ext-all.css"/>

<script type="text/javascript"
    src="http://dev.sencha.com/deploy/ext-3.3.1/adapter/ext/ext-base-debug.js">
</script>
<script type="text/javascript"
    src="http://dev.sencha.com/deploy/ext-3.3.1/ext-all-debug.js">
</script>
    <script type="text/javascript" src="http://dev.sencha.com/deploy/ext-3.3.1/examples/ux/RowExpander.js"></script>


<script type="text/javascript">

function buildWindow() {
var myColumns = [];

var myTemplate = new Ext.Template(
		'<p>&nbsp;&nbsp;<b>Age:</b> {age}</p><br>',
		'<p>&nbsp;&nbsp;<b>Address:</b> {address}</p><br>',
		'<p>&nbsp;&nbsp;<b>City:</b> {city}</p><br>',
		'<p>&nbsp;&nbsp;<b>Zip:</b> {zip}</p><br>'
	);

// row expander
var expander = new Ext.ux.grid.RowExpander({});

expander.on('beforeexpand', function( rowexpander, record, body, rowindex) {
	// make the ajax request
    Ext.Ajax.request({
        url : 'app/users/' + record.get('id') ,
        method: 'GET',
        success: function ( result, request ) {
			// retrive the data
	        var jsonData = Ext.util.JSON.decode(result.responseText);	        
			// pass the data to the overwrite function.
			myTemplate.overwrite(body, jsonData);
        },
        failure: function ( result, request) {
            Ext.MessageBox.alert('Failed', result.responseText);
            return false;
        }
    });
	
	return true;
});

var myStore = new Ext.data.JsonStore({
	url: 'response2.do',
	autoLoad : false, // we will manually call the load function.
	listeners: {
		'load' : function () {
			myStore.each(function(r) {
				myColumns.push(expander);
				// Full Name			
				var this_column = {};		
				r.fields.each(function(currentField) { 
					if(currentField.name == 'fullName') {
						this_column['header'] = 'Full Name';
						this_column['sortable'] = true;
						this_column['dataIndex'] = 'fullName';
						myColumns.push(this_column); 
						return false; // used as a break statement
					}
				});

				// State
				this_column = {};		
				r.fields.each(function(currentField) { 				
					// Ext.grid.Column API docs has complete attribute list.
					if(currentField.name == 'state') {
						this_column['header'] = 'State';
						this_column['sortable'] = true;
						this_column['dataIndex'] = 'state';
						myColumns.push(this_column); 
						return false; // used as a break statement
					}
				});
																	
				return false; // used as a break statement			
			});
			
		}
	}            
});

var grid = new Ext.grid.GridPanel({
	title : 'Name State Grid',
	store : myStore,
	autoHeight : true,
	plugins: expander,
	cm : new Ext.grid.ColumnModel({}), // Empty columnModel initially.
	renderTo : Ext.getBody()
});

// load the data and perform a reconfigure in the callback.
myStore.load({ 
	callback : function(r, options, success) { 
		var myColumnModel = new Ext.grid.ColumnModel({
			columns : myColumns
		});
		grid.reconfigure(myStore, myColumnModel);			
	}
});

}
Ext.onReady(buildWindow);
</script>
 
</head>
<body>
</body>
</html>

Data for Part II

The following files simulate data being returned by a server side resource (Servlet or RESTlet). You can create them using a standard text editor. The files below don’t have an extension so keep that in mind when creating these files in windows.

Note: The information for User 4 is missing on purpose. This is to show the message that would display if information about a user was not found.

response2.do

{ 
"totalCount" : "4",
"records" : [
    {"id" : 1, "state":"NY","fullName":"Ted Williams", "age" : 25},
    {"id" : 2, "state":"NJ","fullName":"Bob Smith", "age" : 37},
    {"id" : 3, "state":"NY","fullName":"John Adams", "age" : 44},
    {"id" : 4, "state":"CA","fullName":"John Doe", "age" : 47}
],
"metaData" : {
	"totalProperty" : 'totalCount',
	"root" : 'records',
	"fields" : ['id', 'state', 'fullName', 'age']	
}
}

app/users/1

{ 
"age" : "45",
"address" : "145-30 Chestnut Street",
"city" : "Rutherford, CT",
"zip" : 10010
}

app/users/2

{ 
"age" : "46",
"address" : "145-31 Chestnut Street",
"city" : "Rutherford, CT",
"zip" : 10010
}

app/users/3

{ 
"age" : "23",
"address" : "145-32 Chestnut Street",
"city" : "Rutherford, CT",
"zip" : 10010
}

That’s All for now!

Advertisements

3 Responses to “ExtJS GridPanel RowExpander With Ajax Call”


  1. 1 aaabbb
    April 9, 2013 at 1:30 am

    Please update to version 4.x

    • April 13, 2017 at 10:45 am

      I had to change the
      myTemplate.overwrite(body,myTemplate);
      to
      myTemplate.overwrite(body, record.data ,myTemplate);
      to get 3.4.1 to send the data to the template to render values.

  2. April 13, 2017 at 10:49 am

    also had to change the myExpander.on(‘beforeexpand’, function( rowexpander, record, body, rowindex) {

    to expand.


Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 77 other followers

March 2011
S M T W T F S
« Feb   Apr »
 12345
6789101112
13141516171819
20212223242526
2728293031  

Blog Stats

  • 846,580 hits

%d bloggers like this: