Set store.pageSize = 19 (or grid.height = 1200) in order to view the top of the dataset later on. This alteration is needed due to a different bug introduced in 4.0.2.

Click "add record". Note a new record is inserted at the top, and existing records shift down as expected. However, the sequence is numbered 1, 2, 2, 3, 4....

Scroll all the way down. The expected end index of 5001 is not there. If the end index is only 4994, that is due to a different bug.

Scroll all the way up. The newly added record at index 1 is no longer there. The original record at index 1 remains.

Optionally, you may choose to refresh the page before the next set of tests. It doesn't effect the outcome whether you do or not.

Click "remove record". Note the record at index 1 is removed as expected. Note that an empty space exists where the record at index store.pageSize + 1 is expected.

Scroll all the way down. Note the index is still 5000 (or 4994), not the expected 4999.

Scroll all the way up. The removed record at index 1 returns.

Refresh the page before the next set of tests.

Click "filter". Note only records with ratings 3 or higher are shown, as expected.

Scroll all the way down. Note the end index is still 5000 (or 4994) and unfiltered records are shown.

Scroll all the way up. Note the filter no longer applies.

In Firefox, it may not be possible to view the topmost record when scrolling back and forth.

The following sequence of steps will cause empty spaces to appear: 1-5 -> 11. However, filtering after a refresh works as expected.

Workaround:
The heart of the workaround at the moment is to manage the full set of records, filtered and unfiltered, outside of the grid and its store. Additions, removals and filtering are processed on the externally managed sets, then swapped into the grid's store.

The fix would be to have the grid's store properly update its prefetchData, snapshot and totalCount. However, that involves a complex sequence of scroller (verticalScroller docking/undocking) and grid view updates we are still investigating.

The set of issues are being brought to the framework developer's attention at this opportune time in the hopes these issues will be resolved by 4.0.2 final.

Fix Part 1: Partial solution to insert issue

The solution below fixes persistence in a buffered grid when inserting records. For ease of testing, the buffer-grid example is used with 50 records generated instead of 5000. store.pageSize is set to 19 to bypass the bug which prevents records at the top from being viewed after scrolling down.

Now the buffered grid can add records, scroll away, scroll back, and still retain the newly added records.

Notes:

This fix has no effect on the issues with removing and filtering records.

Layout issues related to the scrollbars updating properly were avoided. Step through the code from the datachanged trigger to witness the rendering, de-rendering, rendering, then de-rendering of the verticalScrollbar. Will attempt again when layouts are more stable.

When records are added outside of the currently visible range, the currently visible range stays in place. This is due to 2 reasons: business logic here dictates a grid should remain parked for a smoother user experience, and it takes a lot more code in Ext.data.Store.insert() to manage offsets for store.data.

Ext.util.AbstractMixedCollection.insert() was actually performing a replace instead of insert. This fix may break (or fix) other code using this method.

Upon further examination of the framework's code, we have come to the realization the buffer grid is only intended to work with a fixed set of data. Implementing support for inserts, removes and filtering requires massive and fundamental changes to how grids work. At this time, it is best to manage dynamic data outside of the grid before swapping in the altered dataset.

A proper approach would:

Perform inserts and removes on the entire dataset first, not the visible or filtered sets.

Then perform filtering on the entire dataset.

Then perform sorting on the filtered subset.

Then perform paging on the sorted subset to display the visible subset.

Then determine scrollbars based on the visible subset of the sorted subset.

Additionally, empty result sets would have to be permitted at any step (the entire dataset, filtered subset, sorted subset, scrollbar determination).