Hybrid View
-
10 Nov 2012 12:45 PM #1
Grid Reconfigure does not show data in column without reloading store
Grid Reconfigure does not show data in column without reloading store
There maybe several issues with Grid Reconfigure:
I am using Ext 4.1.3 and 4.1.4 but I am pretty sure other close versions have it as well.- If the original column config does not include one locked column, the subsequent metaData configs will ignore the locked columns when loaded.
- When reconfiguring a grid with new columns and the same store, data does not show on the newly shown columns.
- I am assuming here that we don't need to reload the store if the original one had the fields I need it.
- When reconfiguring from regular columns to grouped columns with the same store, some columns get misplaced, others show no data as in item 2.
- When reconfiguring from grouped columns to remove some of the other groups, headers get removed but not the columns
- gridDynamic.html
- gridDynamic.js
- prods.json and prods2.json
gridDynamic.jsHTML Code:<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Dynamic Grid example</title> <link rel="stylesheet" type="text/css" href="../../../extjs-4.1.4/resources/css/ext-all.css" /> <link rel="stylesheet" type="text/css" href="../../../extjs-4.1.4/examples/shared/example.css" /> <style> .bugDiv { margin: 10px 20px;color:gray;} #grid-example { margin: 15px 0 0 25px;} </style> <script type="text/javascript" src="../../../extjs-4.1.4/ext-all-debug.js"></script> <script type="text/javascript" src="gridDynamic.js"></script> </head> <body> <h2>Dynamic Grid Testing</h2> <p>This page test cases the grid reconfig functionality. The buttons on the toolbar execute the different test cases</p> <p>1: On initial page load, the grid is configured to one locked column and it loads data without firing the <i>metachange</i> event.</p> <div class="bugDiv"> <b>Bug 1:</b> If the original config does not include one locked column, the subsequent metaData configs will ignore the locked columns. </div> <p>2: <b>Swap to Group & Swap (no Grouping)</b> Reconfigures grid redefining the store by loading it and firing the <i>metachange</i> event. This correctly reconfigures the grid. (Note bug 1 however) </p> <p>3. <b>Swap (no reload)</b> In this case I am trying to reconfigure the grid to show only certain columns (no change on the store). Shouldn't data be shown in the new columns? </p> <p>4. <b>Swap from no group to grouped cols: </b> </p> <div class="bugDiv"> <p>a. Reload page and click on Swap (no grouping)</p> <p>b. click on Swap (no reload). Notice the type column data is now on the status column and the expires data is missing</p> </p> </div> <p>5. <b>Swap from grouped columns to reconfigure: </b> </p> <div class="bugDiv"> <p>a. Reload page and click on Swap to group</p> <p>b. click on Swap (no reload). Notice the headers were removed but not the columns</p> </p> </div> <p>6: <b>Swap to Original:</b> Correctly reconfigures the grid to the original store/column setup but locked column is gone. <b>Bug 3</b> (or related to bug 1?) </p> <div id="grid-example"></div> </body> </html>
prods.jsonCode:Ext.define('TestModel', { extend: 'Ext.data.Model', fields: [ { "name": "id", "type": "int" } ,{ "name": "name", "type": "string" } ,{ "name": "type", "type": "string" } ,{ "name": "castatus", "type": "string" } ,{ "name": "nystatus", "type": "string" } ,{ "name": "caexpire", "type": "date" } ,{ "name": "nyexpire", "type": "date" } ] }); Ext.define('TestStore',{ extend: 'Ext.data.Store' ,alias: 'widget.teststore' ,proxy: { type: 'ajax', url : '../data/prods.json', reader: { type: 'json' ,root: 'data' } } }); Ext.define('TestGrid',{ extend: 'Ext.grid.Panel' ,alias: 'widget.testgrid' ,initComponent: function(){ var me=this; // orig store will not have the listener... this.origStore = new TestStore({ storeId: 'prodStore' ,fields: this.getAllFields() }); this.store = this.origStore; this.columns = [ // Bug 1: if no column is specified, locking does not seem to work with metaData { text: 'Name', dataIndex: 'name', width: 100, locked: true } ]; this.createToolbars(); this.callParent(); } ,doOrigStore: function(){ // Bug 2: returning to the original config "forgets" the locked column this.reconfigure(this.origStore,this.columns); this.store.load(); } ,swapGridConfig: function(btn){ // Swapping the store and the columns. This works fine switch (btn.configOption) { case 2: var newCols = undefined ,url = '../data/prods.json'; break; case 3: var newCols = [ { "xtype": 'rownumberer', "width": 35, "locked": true } ,{ "text": "Name", "dataIndex": "name","width":100,"locked": true } ,{ "text": "ID", "dataIndex": "id", "width": 60 } ]; var url = '../data/prods2.json'; break; } var newStore = new TestStore({ storeId: 'gridStore' + btn.configOption ,grid: this ,proxy: { url: url, type: 'ajax', reader: { type: 'json' ,root: 'data' } } ,listeners: { 'metachange': function(store, meta) { this.grid.reconfigure(store, meta.columns); } } }); this.store = newStore; this.reconfigure(this.store,newCols); this.store.load(); } ,swapGridColGroupConfig: function(btn){ // In this example I am swapping the config with a new grouped col config (basically removing other states) var newCols = [ { "text": "Name", "dataIndex": "name","width":100, "locked": true } ,{ "text": "CA" ,"itemId": "CA" ,"columns": [ { "text": "Status", "dataIndex": "castatus", "width": 60 } ,{ "text": "Expires", "dataIndex": "caexpire", "width": 60, "format": 'Y-j-m' } ] } ]; if(btn.configOption ===6){ // this will work because I am reloading the store var newStore = new TestStore({ storeId: 'gridStoreGroupTest' ,grid: this ,proxy: { url: '../data/prods.json', type: 'ajax', reader: { type: 'json' ,root: 'data' } } }); this.store = newStore; this.store.load(); } // But without reloading, the new columns have no data using the same store! this.reconfigure(this.store,newCols); //console.log(this.store); //newStore.load(); } ,getAllFields: function(){ return [ { "name": "id", "type": "int" } ,{ "name": "name", "type": "string" } ,{ "name": "type", "type": "string" } ,{ "name": "castatus", "type": "string" } ,{ "name": "nystatus", "type": "string" } ,{ "name": "caexpire", "type": "date" } ,{ "name": "nyexpire", "type": "date" } ]; } ,createToolbars: function(){ this.dockedItems = [ { xtype: 'toolbar' ,dock: 'top' ,items: [ { xtype: 'button' ,text: 'Swap to Orig' ,configOption: 1 ,tooltip: {text:'Swaps back to original config'} ,scope: this ,handler: this.doOrigStore } ,{ xtype: 'button' ,text: 'Swap to Group' ,tooltip: {text:'Swaps to grouped columns and store with metaData config'} ,configOption: 2 ,scope: this ,handler: this.swapGridConfig } ,{ xtype: 'button' ,text: 'Swap (no Grouping)' ,tooltip: {text:'Swaps columns and store with metaData config'} ,configOption: 3 ,scope: this ,handler: this.swapGridConfig } ,{ xtype: 'button' ,text: 'Swap (no reload)' ,tooltip: {text:'reconfigure columns without loading store'} ,configOption: 4 ,scope: this ,handler: this.swapGridColGroupConfig //this.swapState } ,{ xtype: 'button' ,text: 'CA' ,tooltip: {text:'reconfigure columns without loading store. Should not data show?'} ,configOption: 5 ,scope: this ,handler: this.swapGridColGroupConfig //this.swapState } ,{ xtype: 'button' ,text: 'NY' ,tooltip: {text:'reconfigure columns loading store'} ,configOption: 6 ,scope: this ,handler: this.swapGridColGroupConfig //this.swapState } ] } ,{ xtype: 'toolbar', dock: 'bottom', items: [{ xtype: 'pagingtoolbar' ,store: this.store ,pageSize: 25 ,border: false ,displayInfo: true ,displayMsg: 'Records {0} - {1} of {2}' } ] } ] return this.dockedItems; } }); Ext.onReady(function() { Ext.QuickTips.init(); var grid = new TestGrid({ xtype: 'testgrid' ,itemId: 'test-grid' ,title: 'Grid Reconfigure' ,height: 200 ,width: 500 ,renderTo: Ext.get('grid-example') }); Ext.StoreMgr.lookup('prodStore').loadPage(1); });
prods.jsonCode:{ "data": [ { "id": 1, "name": "Product One", "castatus": "Approved", "caexpire": "September, 10 2012 00:00:00", "nystatus": "Rejected", "nyexpire": "November, 21 2012 00:00:00", "type": "Type 1" }, { "id": 2, "name": "Product Two", "castatus": "Approved", "caexpire": "January, 1 2012 00:00:00", "nystatus": "Rejected", "nyexpire": "November, 21 2012 00:00:00", "type": "Type 2" } ] ,"metaData": { "fields": [ { "name": "id", "type": "int" } ,{ "name": "name", "type": "string" } ,{ "name": "type", "type": "string" } ,{ "name": "castatus", "type": "string" } ,{ "name": "nystatus", "type": "string" } ,{ "name": "caexpire", "type": "date" } ,{ "name": "nyexpire", "type": "date" } ], "columns": [ { "xtype": 'rownumberer', "width": 35, "locked": true } ,{ "text": "Name", "dataIndex": "name","width":100, "locked": true } ,{ "text": "CA" ,"itemId": "CA" ,"columns": [ { "text": "Status", "dataIndex": "castatus", "width": 60 } ,{ "text": "Expires", "dataIndex": "caexpire", "width": 60, "format": 'Y-j-m' } ] } ,{ "text": "NY" ,"itemId": "NY" ,"columns": [ { "text": "Status", "dataIndex": "nystatus", "width": 60 } ,{ "text": "Expires", "dataIndex": "nyexpire", "width": 60 , "format": 'Y-j-m'} ] } ,{ "text": "type", "dataIndex": "type" } ] } }
Code:{ "data": [ { "id": 1, "name": "Product One", "castatus": "Approved", "caexpire": "September, 10 2012 00:00:00", "nystatus": "Rejected", "nyexpire": "November, 21 2012 00:00:00", "type": "Type 1" }, { "id": 2, "name": "Product Two", "castatus": "Approved", "caexpire": "January, 1 2012 00:00:00", "nystatus": "Rejected", "nyexpire": "November, 21 2012 00:00:00", "type": "Type 2" } ] ,"metaData": { "fields": [ { "name": "id", "type": "int" } ,{ "name": "name", "type": "string" } ,{ "name": "type", "type": "string" } ,{ "name": "castatus", "type": "string" } ,{ "name": "nystatus", "type": "string" } ,{ "name": "caexpire", "type": "date" } ,{ "name": "nyexpire", "type": "date" } ], "columns": [ { "text": "Name", "dataIndex": "name","width":100, "locked": true } ,{ "text": "type", "dataIndex": "type" } ] } }Last edited by JGALFO; 12 Nov 2012 at 10:13 AM. Reason: Suggested changes
-
12 Nov 2012 7:57 AM #2
It looks like the way you wrote and used the test store there won't be any listeners on it when it is created in the grid.
wipes away the listeners on the stores prototype.Code:listeners: {}
For the most part you should never need to do a query to reference an object that gets created in related code. There are many ways to get a reference with different scopes and closures. One suggestion would be to add the listeners when the store is created and not on the class definition.
Inside the initComponent something like this would work:
Or even something like this:Code:this.origStore = new TestStore({ storeId: 'prodStore', fields: this.getAllFields(), listeners: { 'metachange': function(store, meta) { this.reconfigure(store, meta.columns); }, scope: this } });
Code:this.origStore = new TestStore({ storeId: 'prodStore', fields: this.getAllFields(), grid: this, listeners: { 'metachange': function(store, meta) { this.grid.reconfigure(store, meta.columns); } });
-
12 Nov 2012 9:42 AM #3
Thanks. That makes sense. I've modified the code to your suggestions but the issues noted above still stand.
-
12 Nov 2012 5:43 PM #4
#1,
You need to let the grid know you want locking functionality, you do this by either:
1) Specifying locked columns
2) Adding the enableLocking flag
Otherwise the grid would need to initialize locking in pretty much all cases.
#2,
It's a minor bug when you rebind the same store. For now just pass null instead of the same store to work around it.
#3/#4
Not sure how to reproduce this from your test case, I didn't see any odd behaviour. If you apply the fix to your test case (passing null instead of the same store), is it still reproducible? If so, please post the steps to replicate the problem.Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
-
13 Nov 2012 8:48 AM #5
#2 is Fixed with the workaround you specified. Now grids correctly reconfigure the columns without having to necessarily load the store. #3 and #4 were related, they also work fine now.
#1. I still can't get this to work as I think it should: The following are steps to reproduce.- Use my new code attached as the gridDynamic.js which includes your suggested fixes.
- On load, the original store is configured to use one locked column (note that if you remove the locked:true on the this.columns array all subsequent reconfigures that include the locking on the json data will be ignored). As you see in the code I am trying to force the enableLocking property accordingly. (unless there's some other way I am supposed to do it)
- After initial load click on Swap to group. Note that depending on how the initial lock property was set you will or will not see the locking.
- From step 3, click on Swap (NoGroup/NoLock). Notice again that depending on the initial lock property you do or do not see the lock. In this case you should not see it at all but you do in the rowcolumn.
- Finally, now click on Swap to Orig and notice that now the lock is gone even though I am trying to force it on.
Thanks.
By the way, I think a similar test case would make a good candidate for the grid examples.
Code:Ext.define('TestModel', { extend: 'Ext.data.Model', fields: [ { "name": "id", "type": "int" } ,{ "name": "name", "type": "string" } ,{ "name": "type", "type": "string" } ,{ "name": "castatus", "type": "string" } ,{ "name": "nystatus", "type": "string" } ,{ "name": "caexpire", "type": "date" } ,{ "name": "nyexpire", "type": "date" } ] }); Ext.define('TestStore',{ extend: 'Ext.data.Store' ,alias: 'widget.teststore' ,proxy: { type: 'ajax', url : '../data/prods.json', reader: { type: 'json' ,root: 'data' } } }); Ext.define('TestGrid',{ extend: 'Ext.grid.Panel' ,alias: 'widget.testgrid' ,initComponent: function(){ var me=this; // orig store will not have the listener... this.origStore = new TestStore({ storeId: 'prodStore' ,fields: this.getAllFields() }); this.store = this.origStore; this.columns = [ // Bug 1: if no column is specified, locking does not seem to work with metaData { text: 'Name', dataIndex: 'name', width: 100, locked: true } ]; this.createToolbars(); this.callParent(); } ,doOrigStore: function(){ // Bug 2: returning to the original config "forgets" the locked column this.store = new TestStore({ storeId: 'prodStore' ,fields: this.getAllFields() }); this.enableLocking = true; this.reconfigure(null,this.columns); this.store.load(); } ,swapNoLock: function(btn){ var newCols = [ { "xtype": 'rownumberer', "width": 35 } ,{ "text": "Name", "dataIndex": "name","width":100 } ,{ "text": "ID", "dataIndex": "id", "width": 60 } ] ,url = '../data/prods2.json'; var newStore = new TestStore({ storeId: 'gridStore' + btn.configOption ,grid: this ,proxy: { url: url, type: 'ajax', reader: { type: 'json' ,root: 'data' } } }); this.store = newStore; this.enableLocking = false; this.reconfigure(null,newCols); console.log('enableLocking: ',this.enableLocking ); this.store.load(); } ,swapGridConfig: function(btn){ // Swapping the store and the columns. This works fine var newCols = undefined ,url = '../data/prods.json'; var newStore = new TestStore({ storeId: 'gridStore' + btn.configOption ,grid: this ,proxy: { url: url, type: 'ajax', reader: { type: 'json' ,root: 'data' } } ,listeners: { 'metachange': function(store, meta) { this.grid.reconfigure(store, meta.columns); } } }); this.store = newStore; this.enableLocking = true; this.reconfigure(null,newCols); console.log('enableLocking: ',this.enableLocking ); this.store.load(); } ,swapGridColGroupConfig: function(btn){ // In this example I am swapping the config with a new grouped col config (basically removing other states) var newCols = [ { "text": "Name", "dataIndex": "name","width":100, "locked": true } ,{ "text": "CA" ,"itemId": "CA" ,"columns": [ { "text": "Status", "dataIndex": "castatus", "width": 60 } ,{ "text": "Expires", "dataIndex": "caexpire", "width": 60, "format": 'Y-j-m' } ] } ]; if(btn.configOption ===6){ // this will work because I am reloading the store var newStore = new TestStore({ storeId: 'gridStoreGroupTest' ,grid: this ,proxy: { url: '../data/prods.json', type: 'ajax', reader: { type: 'json' ,root: 'data' } } }); this.store = newStore; this.store.load(); } // But without reloading, the new columns have no data using the same store! // specifying null instead of this.store when re-binding a store this.reconfigure(null,newCols); //console.log(this.store); //newStore.load(); } ,getAllFields: function(){ return [ { "name": "id", "type": "int" } ,{ "name": "name", "type": "string" } ,{ "name": "type", "type": "string" } ,{ "name": "castatus", "type": "string" } ,{ "name": "nystatus", "type": "string" } ,{ "name": "caexpire", "type": "date" } ,{ "name": "nyexpire", "type": "date" } ]; } ,createToolbars: function(){ this.dockedItems = [ { xtype: 'toolbar' ,dock: 'top' ,items: [ { xtype: 'button' ,text: 'Swap to Orig' ,configOption: 1 ,tooltip: {text:'Swaps back to original config'} ,scope: this ,handler: this.doOrigStore } ,{ xtype: 'button' ,text: 'Swap to Group' ,tooltip: {text:'Swaps to grouped columns and store with metaData config'} ,configOption: 2 ,scope: this ,handler: this.swapGridConfig } ,{ xtype: 'button' ,text: 'Swap (NoGroup/NoLock)' ,tooltip: {text:'Swaps columns and store with metaData config'} ,configOption: 3 ,scope: this ,handler: this.swapNoLock } ,{ xtype: 'button' ,text: 'Swap (no reload)' ,tooltip: {text:'reconfigure columns without loading store'} ,configOption: 4 ,scope: this ,handler: this.swapGridColGroupConfig //this.swapState } ,{ xtype: 'button' ,text: 'CA' ,tooltip: {text:'reconfigure columns without loading store. Should not data show?'} ,configOption: 5 ,scope: this ,handler: this.swapGridColGroupConfig //this.swapState } ,{ xtype: 'button' ,text: 'NY' ,tooltip: {text:'reconfigure columns loading store'} ,configOption: 6 ,scope: this ,handler: this.swapGridColGroupConfig //this.swapState } ] } ,{ xtype: 'toolbar', dock: 'bottom', items: [{ xtype: 'pagingtoolbar' ,store: this.store ,pageSize: 25 ,border: false ,displayInfo: true ,displayMsg: 'Records {0} - {1} of {2}' } ] } ] return this.dockedItems; } }); Ext.onReady(function() { Ext.QuickTips.init(); var grid = new TestGrid({ xtype: 'testgrid' ,itemId: 'test-grid' ,title: 'Grid Reconfigure' ,height: 200 ,width: 500 ,renderTo: Ext.get('grid-example') }); Ext.StoreMgr.lookup('prodStore').loadPage(1); });
-
13 Nov 2012 9:28 PM #6
You need to configure enableLocking up front, setting the property at runtime has no effect.
Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
Success! Looks like we've fixed this one. According to our records the fix was applied for
EXTJSIV-7742
in
4.2.0 Sprint 2.



Reply With Quote