PDA

View Full Version : grid filter- how to recalc number of records to show?



ironandsteel
5 Feb 2012, 9:01 AM
I have a grid app in which I want to use filters. I am doing remote filtering. I initially load all the data into the store and it displays fine. I select a "category code" from a combobox, and this calls filter on the store.

Since the store is set to remote filtering, it makes an ajax call to my server script, and I get back a new set of records with my filter applied. So far so good.

Lets say that this filter operation returned 7 records. Now, if I pick another filter category which has, say, 11 results, the correct ajax call is made, and the correct data is returned, including the correct count of records in the json. The problem is that only the first 7 records are shown in the grid rather than all 11.

What is the correct way to cause it to recalculate how many rows to display in the grid?

Here is the store:



// create the contractor Data Store
var ContractorStore = Ext.create('Ext.data.Store',
{
id: 'contstore',
pageSize: 200
model: 'Contractor.Model',
autoLoad: false,
autoSync: true,
remoteSort: true,
remoteFilter: true,
buffered: true,
purgePageCount: 0,
proxy: {
id: 'contractorStoreProxy',
autoSync: true,
type: 'ajax',
api: {
read: '../scripts/getContListChunk.php', // works fine
create: '../scripts/createContRecord.php', //
update: '../scripts/updateContRecord.php',
destroy: '../scripts/deleteContRecord.php'
}
,reader: {
type: 'json',
root: 'rows',
totalProperty: 'total'

}
,writer: {
type: 'json',
writeAllFields: false,
root: 'rows'
}
,simpleSortMode: true
}
});


Here is how the store gets loaded:


ContractorStore.prefetch(
{
start: 0
,limit: 5000
,filters:[
{id: "sel", property: "sel", value: 'false' },
{id: "catcode", property: "catcode", value: 'all'}
]
,callback: function()
{
ContractorStore.guaranteeRange(0, 600);
}
});


Here is where I call filter on the store as a result of selecting a filter category from the combobox. "Sel" is a checkbox that is for another purpose.


this.ownerCt.ownerCt.store.filter([
{id: "sel", property: "sel", value: selOnly },
{id: "catcode", property: "catcode", value: catCode}
]);


Currently I'm using 4.1b2.
Thanks-
LK

mitchellsimoens
5 Feb 2012, 9:40 AM
Have you checked the store to see what it has loaded to see if all 11 are in there correctly?

ironandsteel
5 Feb 2012, 10:23 AM
Have you checked the store to see what it has loaded to see if all 11 are in there correctly?

Good question. I see that the store contains 7 records- they are the first 7 records of the proper 11. So, the grid is correctly displaying what is in the store. The store is just not loading all 11 records- only the first 7.

I'm going to try to trace this. If you have any idea of things to check, let me know.

Thanks for the response, Mitchell (esp on Super Bowl Sunday)
LK

ironandsteel
5 Feb 2012, 10:41 AM
I've traced into the extjs and found something that looks wrong- what do you think? I added a couple comments indicating what looks wrong to me. Basically it seems to be passing the current number of records into me.loadRecords- which makes no sense..I think.



//line 69965 in debug w comments
if (me.remoteFilter) {
// For a buffered Store, we have to clear the prefetch cache because the dataset will change upon filtering.
// Then we must prefetch the new page 1, and when that arrives, reload the visible part of the Store if (me.buffered) {
count = me.getCount(); // this is the count of the OLD data- why do we care?
me.prefetchData.clear();
me.prefetchPage(1, {
callback: function(records, operation, success) {
if (success) {
me.guaranteedStart = 0;
me.guaranteedEnd = records.length - 1;
//the next line loads records using the count of the OLD records(7 in my example)- looks wrong
me.loadRecords(Ext.Array.slice(records, 0, count)); } } });
} else {
// Reset to the first page, the filter is likely to produce a smaller data set
me.currentPage = 1;
//the load function will pick up the new filters and request the filtered data from the proxy me.load();
}

ironandsteel
5 Feb 2012, 11:40 AM
I have made a temporary hack until this is figured out.


// line 69976 of debug with comments
//me.loadRecords(Ext.Array.slice(records, 0, count)); //replaced with line below
me.loadRecords(Ext.Array.slice(records, 0, records.length));


This makes my grid do the right thing with regard to the filter. The glitch that remains is that if the number of records returned is > the store pagesize, then it doesn't pull in the next page properly. For now, I have set the page size to 5000, which renders buffered scrolling moot, but it all works, albeit slowly.

I'm hoping that this issue will be addressed and documented well in upcoming versions.

I'm strongly considering going back to 3.4 at this point, especially if I can get the old buffered grid approach to work- I have burned weeks trying to make 4.1 work for me...
Thanks-
LK

Animal
6 Feb 2012, 9:29 AM
The number of records in the Store is the number of rows shown.

This has always been the case.

We do probably need to recalculate an appropriate automatic pageSize if the Store size ever changes upon load.

We'd have to cache the store count, and then upon subsequent loads test for a change, and then recalculate a new pageSize.

pageSize 5000 does not affect buffered scrolling. That's just how much data is pulled into the prefetch cache at one time. It's the number of records loaded into the Store itself which will affect performance - they are mapped into the UI.

I think this qualifies as a bug. In the meantime, you can force the pageSize to be recalculated by



delete myStore.pageSize;
myGrid.verticalScroller.onViewResize(null, null, myGrid.view.getHeight());


Because it does attempt to recalculate a good page size when the view changes size. (But it will not override an existing page size - which I think is also a bug so you have to delete it first)

Animal
6 Feb 2012, 9:31 AM
By doing



me.loadRecords(Ext.Array.slice(records, 0, records.length));


You are loading the entire prefetched cache into the Store. This is not what you want.

The Store size should staye the same.

That's why getCount() was cached. So that the same size batch of records is pulled through from the prefetch buffer into the Store.

ironandsteel
6 Feb 2012, 10:29 AM
I think this qualifies as a bug. In the meantime, you can force the pageSize to be recalculated by



delete myStore.pageSize;
myGrid.verticalScroller.onViewResize(null, null, myGrid.view.getHeight());



Animal- thanks so much for the reply! Alas, your fix doesn't seem to do it for me. In my example, I still only see the first 7 records. I put your code in the listener for my combobox that picks the category to filter by, just before I call filter():


,listeners:{"select":function(theCombo, newValue, oldValue, eOpts)
{
var catCode = newValue[0].data.value;
var selOnly = Ext.getCmp('checkedOnly').getValue();
delete this.ownerCt.ownerCt.store.pageSize;
// pageHt is always 412 when I look in debugger; pageSize on my store is 400- dunno where is gets 412
var pageHt = this.ownerCt.ownerCt.view.getHeight();
this.ownerCt.ownerCt.verticalScroller.onViewResize(null, null, pageHt);
this.ownerCt.ownerCt.store.filter([
{id: "sel", property: "sel", value: selOnly },
{id: "catcode", property: "catcode", value: catCode}
]);
}


p.s. - is there a cleaner way to get hold of the grid from inside of the listener for a combobox which is inside a toolbar? ownerCt.ownerCt works but seems inelegant...