-
6 Oct 2009 9:12 AM #1
[CLOSED]Grid removeAll() and PagingToolbar refreshing
[CLOSED]Grid removeAll() and PagingToolbar refreshing
It would appear from the documentation that, to clear a Store, one calls removeAll().
My grid correctly refreshes to show no records.
However, the pager display message remains the same... I would have expected the emptyMsg to kick in at this point.
Am I doing something wrong, or is this a bug?
Thanks,
Mark.
-
7 Oct 2009 12:56 AM #2Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 41
Yes, I believe this should be qualified as a bug.
Here's a fix:
Known issue: Fires change event twice when loading.Code:Ext.override(Ext.data.Store, { add : function(records){ records = [].concat(records); if(records.length < 1){ return; } for(var i = 0, len = records.length; i < len; i++){ records[i].join(this); } var index = this.data.length; this.data.addAll(records); if(this.snapshot){ this.snapshot.addAll(records); } this.totalLength += records.length; this.fireEvent('add', this, records, index); }, remove : function(record){ if(Ext.isArray(record)){ Ext.each(record, function(r){ this.remove(r); }, this); } var index = this.data.indexOf(record); if(index > -1){ record.join(null); this.data.removeAt(index); if(this.pruneModifiedRecords){ this.modified.remove(record); } if(this.snapshot){ this.snapshot.remove(record); } this.totalLength--; this.fireEvent('remove', this, record, index); } }, removeAll : function(){ var items = []; this.each(function(rec){ items.push(rec); }); this.clearData(); if(this.snapshot){ this.snapshot.clear(); } if(this.pruneModifiedRecords){ this.modified = []; } this.totalLength = 0; this.fireEvent('clear', this, items); } }); Ext.override(Ext.PagingToolbar, { bindStore : function(store, initial){ var doLoad; if(!initial && this.store){ if(store !== this.store && this.store.autoDestroy){ this.store.destroy(); }else{ this.store.un('beforeload', this.beforeLoad, this); this.store.un('load', this.onLoad, this); this.store.un('exception', this.onLoadError, this); this.store.un('datachanged', this.onChange, this); this.store.un('add', this.onChange, this); this.store.un('remove', this.onChange, this); this.store.un('clear', this.onClear, this); } if(!store){ this.store = null; } } if(store){ store = Ext.StoreMgr.lookup(store); store.on({ scope: this, beforeload: this.beforeLoad, load: this.onLoad, exception: this.onLoadError, datachanged: this.onChange, add: this.onChange, remove: this.onChange, clear: this.onClear }); doLoad = true; } this.store = store; if(doLoad){ this.onLoad(store, null, {}); } }, onLoad : function(store, r, o){ if(!this.rendered){ this.dsLoaded = [store, r, o]; return; } var p = this.getParams(); this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0; this.onChange(); }, onChange : function(){ if(this.rendered){ var d = this.getPageData(), ap = d.activePage, ps = d.pages; this.afterTextItem.setText(String.format(this.afterPageText, d.pages)); this.inputItem.setValue(ap); this.first.setDisabled(ap == 1); this.prev.setDisabled(ap == 1); this.next.setDisabled(ap == ps); this.last.setDisabled(ap == ps); this.refresh.enable(); this.updateInfo(); } this.fireEvent('change', this, d); }, onClear : function(){ this.cursor = 0; this.onChange(); } });Last edited by Condor; 23 Oct 2009 at 3:56 AM. Reason: Added datachanged event for filtering support
-
7 Oct 2009 2:35 AM #3
Excellent! Thank you. Presumably this will be picked up as a bug, or do I need to do something to escalate it - would be a shame for your code not to be integrated

Mark.
-
15 Oct 2009 10:04 PM #4
I don't necessarily agree with this. There have been several discussions about local manipulation of a paging toolbar. There are several issues.
Say I have 20 items on the first page and I add a new record locally. What should happen? Same with removing a single record on a page of 20, should the server re-request another record from the server?
I think it's best to leave this up to the developer, PagingToolbar is really only intended for use with "remote" stores.Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
-
23 Oct 2009 5:37 AM #5
Could it be an option if dissociate the PagingToolbar to two classes, one for remote paging and to another for local paging? Remote and local data handling is too different from eachother, my point is that cannot handle all two cases in one class. So my idea to solve all of these problems to make data handling classes as abstarct classes, then make - for example - a LocalStore and a RemoteStore, etc..., LocalPagingStore and RemotePagingStore.
I haven`t know a case in practise that handle a recordset locally and remotly in the same time, all data handling should only locally or remotly.
Separating these two cases can results a clearest interface I think.
What do you think about this option? Is this a way?AdHoc PHP Framework developer, permanent ExtJS fan
My old extensions:My old patches:
-
23 Oct 2009 5:44 AM #6Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 41
You could extend PagingToolbar instead of overriding it.
Also, my PagingStore user extension (for local paging) doesn't need the add/remove/removeAll patches described above.
-
27 Oct 2009 4:58 AM #7
@prometheus Possibly, but it presents some challenges.
Anyway, from the initial report, this isn't a bug, so I'm going to mark this one as closed.Evan Trimboli
Sencha Developer
Twitter - @evantrimboli
Don't be afraid of the source code!
-
6 Apr 2010 8:26 AM #8
@Condor: Thanks for the patch!
Complete patch for ExtJS 3.2, note the Store insert() function also needs to be overridden:
Code:/* Paging toolbar enhancements:*/ Ext.override(Ext.data.Store, { add : function(records){ records = [].concat(records); if(records.length < 1){ return; } for(var i = 0, len = records.length; i < len; i++){ records[i].join(this); } var index = this.data.length; this.data.addAll(records); if(this.snapshot){ this.snapshot.addAll(records); } this.totalLength += records.length; this.fireEvent('add', this, records, index); }, insert : function(index, records) { records = [].concat(records); for(var i = 0, len = records.length; i < len; i++){ this.data.insert(index, records[i]); records[i].join(this); } if(this.snapshot){ this.snapshot.addAll(records); } this.totalLength += records.length; this.fireEvent('add', this, records, index); }, remove : function(record){ if(Ext.isArray(record)){ Ext.each(record, function(r){ this.remove(r); }, this); } var index = this.data.indexOf(record); if(index > -1){ record.join(null); this.data.removeAt(index); this.totalLength--; } if(this.pruneModifiedRecords){ this.modified.remove(record); } if(this.snapshot){ this.snapshot.remove(record); } if(index > -1){ this.fireEvent('remove', this, record, index); } }, removeAll : function(silent){ var items = []; this.each(function(rec){ items.push(rec); }); this.clearData(); this.totalLength = 0; if(this.snapshot){ this.snapshot.clear(); } if(this.pruneModifiedRecords){ this.modified = []; } if (silent !== true) { // <-- prevents write-actions when we just want to clear a store. this.fireEvent('clear', this, items); } } }); Ext.override(Ext.PagingToolbar, { bindStore : function(store, initial){ var doLoad; if(!initial && this.store){ if(store !== this.store && this.store.autoDestroy){ this.store.destroy(); }else{ this.store.un('beforeload', this.beforeLoad, this); this.store.un('load', this.onLoad, this); this.store.un('exception', this.onLoadError, this); this.store.un('datachanged', this.onChange, this); this.store.un('add', this.onChange, this); this.store.un('remove', this.onChange, this); this.store.un('clear', this.onClear, this); } if(!store){ this.store = null; } } if(store){ store = Ext.StoreMgr.lookup(store); store.on({ scope: this, beforeload: this.beforeLoad, load: this.onLoad, exception: this.onLoadError, datachanged: this.onChange, add: this.onChange, remove: this.onChange, clear: this.onClear }); doLoad = true; } this.store = store; if(doLoad){ this.onLoad(store, null, {}); } }, onLoad : function(store, r, o){ if(!this.rendered){ this.dsLoaded = [store, r, o]; return; } var p = this.getParams(); this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0; var d = this.getPageData(), ap = d.activePage, ps = d.pages; this.onChange(); }, onChange : function() { if(this.rendered){ var d = this.getPageData(), ap = d.activePage, ps = d.pages; this.afterTextItem.setText(String.format(this.afterPageText, d.pages)); this.inputItem.setValue(ap); this.first.setDisabled(ap == 1); this.prev.setDisabled(ap == 1); this.next.setDisabled(ap == ps); this.last.setDisabled(ap == ps); this.refresh.enable(); this.updateInfo(); } this.fireEvent('change', this, d); }, onClear : function(){ this.cursor = 0; this.onChange(); } });
-
1 Jun 2010 6:55 PM #9
Hi,
I'm trying to implement the above, add new record(s) to the first page but always keep the first page the same records as 'limit' size, but seems there are some problems with it.
The drop-in example add record and the plugin will remove the last old record after 'add' event, after the event fired, I found that the store really removed the last record, but the last record is still on the screen. is it a bug?Code:<html> <head> <title>Test Grid</title> <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css"/> <!-- GC --> <!-- LIBS --> <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script> <!-- ENDLIBS --> <script type="text/javascript" src="../../ext-all.js"></script> <style type="text/css"> html, body { font: normal 12px verdana; margin: 0; padding: 0; border: 0 none; } </style> <script type="text/javascript"> Ext.ns('Ext.grid.plugins'); Ext.grid.plugins.FixedRowNo = Ext.extend(Object, { init: function(grid){ this.grid = grid; grid.store.on('add', this.trimRow, this); }, trimRow: function(store){ var showStore = function(s) { for (var i = 0; i < s.getCount(); i++) { var r = s.getAt(i); console.log((i+1), r.get('company')); }; } showStore(store); var max = this.grid.maxRow;//store.lastOptions.params.limit; if (max) { var count = store.getCount(); if (count > max) { for (var i = count; i > max; i--) { //store.removeAt(i-1); var record = store.getAt(i-1); store.remove(record); console.log("removed=",record); } } } showStore(store); } }); Ext.preg('fixedrowno', Ext.grid.plugins.FixedRowNo); Ext.onReady(function() { var myData = [ ['3m Co',71.72,0.02,0.03,'9/1 12:00am'], ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'], ['Altria Group Inc',83.81,0.28,0.34,'9/1 12:00am'], ['American Express Company',52.55,0.01,0.02,'9/1 12:00am'], ['American International Group, Inc.',64.13,0.31,0.49,'9/1 12:00am'], ['AT&T Inc.',31.61,-0.48,-1.54,'9/1 12:00am'], ]; /** * Custom function used for column renderer * @param {Object} val */ function change(val){ if(val > 0){ return '<span style="color:green;">' + val + '</span>'; }else if(val < 0){ return '<span style="color:red;">' + val + '</span>'; } return val; } /** * Custom function used for column renderer * @param {Object} val */ function pctChange(val){ if(val > 0){ return '<span style="color:green;">' + val + '%</span>'; }else if(val < 0){ return '<span style="color:red;">' + val + '%</span>'; } return val; } // create the data store var store = new Ext.data.ArrayStore({ fields: [ {name: 'company'}, {name: 'price', type: 'float'}, {name: 'change', type: 'float'}, {name: 'pctChange', type: 'float'}, {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'} ] }); // manually load local data store.loadData(myData); // create the Grid var grid = new Ext.grid.GridPanel({ store: store, plugins: ['fixedrowno'], tbar: [{ text: 'add', handler: function() { // access the Record constructor through the grid's store var p = new store.recordType({company: 'Wal-Mart Stores, Inc.', price: 45.45, change: 0.73, pctChange: 1.63, lastChange: new Date()}); store.insert(0, p); } }, { text: 'remove', handler: function() { store.removeAt(store.getCount()-1); } }], columns: [ new Ext.grid.RowNumberer(), {id:'company',header: 'Company', width: 160, sortable: true, dataIndex: 'company'}, {header: 'Price', width: 75, sortable: true, renderer: 'usMoney', dataIndex: 'price'}, {header: 'Change', width: 75, sortable: true, renderer: change, dataIndex: 'change'}, {header: '% Change', width: 75, sortable: true, renderer: pctChange, dataIndex: 'pctChange'}, {header: 'Last Updated', width: 85, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'} ], stripeRows: true, autoExpandColumn: 'company', height: 250, width: 600, title: 'Array Grid', maxRow: myData.length, // config options for stateful behavior stateful: true, stateId: 'grid' }); // render the grid to the specified div in the page grid.render('grid-example'); }); </script> </head> <body> <div id="grid-example"></div> </body> </html>
Thank you.
-
28 Feb 2013 12:35 AM #10
Does this fix as well work with store.reload ()
Does this fix as well work with store.reload ()
Hey guys
I am doing store reload for grid based on some external events. However this fix is not working with store reload. Can anyone please help me out on this ?
Thanks
Samir
Thank you for reporting this bug. We will make it our priority to review this report.


Reply With Quote