View Full Version : Nested Grid with different models from different DB tables

6 Nov 2012, 5:42 AM
I have Account and Transaction tables on SQL Server DB and I'm using PHP & ExtJS 4.1.1a for my front-end

Table fields
ID int PK , MemberID int, OpeningBalance decimal, ClosingBalance decimal, etc
ID int PK, AccountID int FK, EffectiveDate datetime, Reference varchar, Amount decimal.

I can display accounts list in a normal extJS grid with paging--- that fine

My problem is - How can I do nested grid that will show Account list, and on expanding of Account row, show Transaction information related to the expanded account row? Im using JSON return from DB requests.

NB: This need to have different model (which will lead to different grid columns) as you see my table fields above.

The nested grid example on docs, does not explain it well as it is using local store and one model
Please help..! An example or a clue will do... Just please point me to right directions,

Any help or example will be appreciated.

6 Nov 2012, 7:02 AM
Try this plugin https://github.com/mitchellsimoens/Ux.grid.plugin.AssociationRowExpander

6 Nov 2012, 7:09 AM
I advise to create simple TreeStore (that won't connect to server) for the grid and populate it basing on data in Accounts store.
This way you will achieve better events handling.

7 Nov 2012, 11:49 PM
Here is my JSON data 39907

My normal Grid
I can display the accounts data fine, BUT I want to be able to drill to Transactions as per JSON data screen

My JS code

Ext.Loader.setConfig({enabled: true});
Ext.Loader.setPath('Ext.ux', 'scripts/ext-4.1.1a/ux/');



var lm_get_params = {};
var data = jQuery("#reportForm").serializeObject();


//alert('after data check');


Ext.define('AccountReport', {
extend: 'Ext.data.Model',
fields: [
{name: 'MemberID', type: 'int'},
{name: 'MemberName', type: 'string'},
{name: 'AccountNumber', type: 'int'},
{name: 'OpeningBalance', type: 'float'},
{name: 'AvailableBalance', type: 'float'},
{name: 'LastAllocationOn', mapping: 'LastAllocationOn', type: 'date', dateFormat: 'Y-m-d H:i:s'},
{name: 'CreatedOn', mapping: 'CreatedOn', type: 'date', dateFormat: 'Y-m-d H:i:s'},
{name: 'IsActive', type: 'boolean', defaultValue: true},
{name: 'IsClaimed', type: 'boolean', defaultValue: false},
{name: 'IsLocked', type: 'boolean', defaultValue: false},
idProperty: 'ID'

// create the Data Store
var store = Ext.create('Ext.data.Store', {
pageSize: lm_grid_pagesize,
model: 'AccountReport',
remoteSort: false,
proxy: {
// load using script tags for cross domain, if the data in on the same domain as
// this page, an HttpProxy would be better
//type: 'jsonp', //for use when requesting on remote domain
type: 'ajax',
url: lm_url_get,
method: 'POST',
extraParams: lm_get_params,
reader: {
root: 'accounts',
totalProperty: 'totalCount'
// sends single sort as multi parameter
simpleSortMode: true
sorters: [{
property: 'CreatedOn',
direction: 'DESC'

// pluggable renders

* Custom function used for column renderer
* @param {Object} val
function renderMoney(value) {

value = Ext.util.Format.usMoney(value);
value = value.replace('$','R');

return value;

function changeLocked(value) {
if (value == '0') {
return '<span style="color:green;">' + value + '</span>';
} else {
return '<span style="color:red;">' + value + '</span>';
return value;

function changeActive(value) {
if (value == '1') {
return '<span style="color:green;">' + value + '</span>';
} else {
return '<span style="color:red;">' + value + '</span>';
return value;

function changeClaimed(value) {
if (value == '1') {
return '<span style="color:green;">' + value + '</span>';
} else {
return '<span style="color:red;">' + value + '</span>';
return value;

function renderLastAllocation(value) {
//return Ext.String.format('{0}<br/>by {1}', Ext.Date.dateFormat(value, 'M j, Y, g:i a'), r.get('lastposter'));
return Ext.String.format('{0}', Ext.Date.dateFormat(value, 'Y-m-d H:i:s'));

var pluginExpanded = true;
var grid = Ext.create('Ext.grid.Panel', {
width: 1000,
height: 600,
title: 'WGB - Browse Accounts',
store: store,
disableSelection: true,
loadMask: true,
viewConfig: {
id: 'gv',
trackOver: false,
stripeRows: false,
plugins: [{
ptype: 'preview',
bodyField: 'excerpt',
expanded: true,
pluginId: 'preview'
// grid columns
// id assigned so we can apply custom css (e.g. .x-grid-cell-topic b { color:#333 })
// TODO: This poses an issue in subclasses of Grid now because Headers are now Components
// therefore the id will be registered in the ComponentManager and conflict. Need a way to
// add additional CSS classes to the rendered cells.

text: "Account",
dataIndex: 'AccountNumber',
flex: 1,
sortable: true

text: "Member",
dataIndex: 'MemberName',
width: 120,
//hidden: true,
sortable: true

text: "Opening Bal.",
dataIndex: 'OpeningBalance',
width: 100,
//hidden: true,
renderer: renderMoney,
sortable: true

text: "Available Bal",
dataIndex: 'AvailableBalance',
width: 70,
//align: 'right',
renderer: renderMoney,
sortable: true

text: "Last Allocation",
dataIndex: 'LastAllocationOn',
width: 150,
renderer: renderLastAllocation,
sortable: true

text: "Active",
dataIndex: 'IsActive',
width: 100,
renderer: changeActive,
sortable: false

text: "Claimed",
dataIndex: 'IsClaimed',
width: 100,
renderer: changeClaimed,
sortable: false

text: "Locked",
dataIndex: 'IsLocked',
width: 100,
renderer: changeLocked,
sortable: false
// paging bar on the bottom
bbar: Ext.create('Ext.PagingToolbar', {
store: store,
displayInfo: true,
displayMsg: 'Displaying topics {0} - {1} of {2}',
emptyMsg: "No accounts to display" /*,
'-', {
text: 'Show Preview',
pressed: pluginExpanded,
enableToggle: true,
toggleHandler: function(btn, pressed) {
var preview = Ext.getCmp('gv').getPlugin('preview');
renderTo: 'account-grid'

// trigger the data store load
//return false;

Please show me example code, how to drill to Transactions of a selected account on the grid as per grid screen ?

Any help will be appreciated ?