View Full Version : [FIXED] [4.2.2] Grid Selection not deselecting record after loading new data with an id

9 Dec 2013, 3:22 PM
Ext version tested:

Ext 4.1.3
Ext 4.2.2

Browser versions tested against:

FF 25.0.1
Chrome 31.0.1650.57 m

DOCTYPE tested against:



If you load two different sets of data into a store using data with an "id" property, the selection model does not deselect the record correctly because it thinks you are using the same record (when loading a store through loadData). There was a function added inside of Ext.selection.Model class called "storeHasSelected". This appears to be a reason this is occurring. However, it could have something to do with useLinearSearch added to the indexOf function inside of AbstractMixedCollection. In previous version of Extjs 4 (verified in 4.1.3), the row would be deselected.

storeHasSelected: function(record) {
var store = this.store,
len, id, i;

// If two different sets of data are loaded, this check causes the selection model to think it needs to be reselected and does not fire the select event because
// the selection model does not think it has been changed.
if (record.hasId() && store.getById(record.getId())) {
return true;
} else {
records = store.data.items;
len = records.length;
id = record.internalId;

for (i = 0; i < len; ++i) {
if (id === records[i].internalId) {
return true;
return false;

Steps to reproduce the problem:

Setup a simple grid with two different data sets and load the first set of data with loadData.
Select a record and load the second set of data using loadData.

The result that was expected:

When loading the second set of data, the record should be deselected.

The result that occurs instead:

The new data record is selected.

Additional debugging:

I have created a sample grid in the example.zip file to illustrate the problem. I used the following data set for my test.

Data set A:

"id": "1", //comment this out for second test
"id": "2", //comment this out for second test

Data set B:

"id": "1", //comment this out for second test
"id": "2", //comment this out for second test

Test 1:

Go to the index.html page and let the data load.
Select the second record containing the column field 1 and value 11
Click the Load New Data record
Notice new data appears in column field 1. The value is now AA. The row is still highlighted.

The row was not deselected event though the loadData function created a compeletly new record because the "id" property remained the same. Why would you want to select the same "id" if the data is different?

Test: 2

Open the index.html in a text editor and comment out all of the "id" properties for the data.
Go to the index.html page and let the data load.
Select the second record containing the column field 1 and value 11
Click the Load New Data record
Notice new data appears in column field 1. The value is now AA and the row is no longer highlight. This is because storeHasSelected check for id does not return a value and the interalId should be used instead.

10 Dec 2013, 2:54 PM
Here is a fiddle that shows more of the problem. If you look at the console.logs (should do this in chrome or firefox), then you can see the selected record is retained even though it is no longer in the store. If I were doing a real app this would be a lot cleaner, but it is based on my example.zip.


I (https://fiddle.sencha.com/#fiddle/22t)f you swap to 4.1.1 classic, you will see the correct behavior.

11 Dec 2013, 6:31 AM
I ended up filing this with support and here is the Extjs bug number they gave for issue.


16 Dec 2013, 7:41 AM
Any updates on the status of this bug? Is there a workaround for this bug?

16 Dec 2013, 7:54 AM
Haven't heard anything else from sencha. However, I did find this post:


Apparently, its an old known issue. I am not very happy with my fix, but it appears to get the job done. I created an override for the refresh function of the Ext.selection.Model and set the store.data MixedCollection to useLinearSearch. This will tell it to look for the data by the actual data itself instead of looking at keys. You will see a comment like // ADDED - @422. This is where I made my change.

refresh: function() {
var me = this,
store = me.store,
toBeSelected = [],
toBeReAdded = [],
oldSelections = me.getSelection(),
len = oldSelections.length,
i = 0,
lastFocused = me.getLastFocused();

// ADDED - @422 - This is a temp fix for an indexOf change. It is causing problems with selection models on grids because
// if you have two completely sets of data that return an id with the response, the selection model thinks that the ids are identical and
// prevent deselection of the record.
store.data.useLinearSearch = true;

// Not been bound yet.
if (!store) {

// Add currently records to the toBeSelected list if present in the Store
// If they are not present, and pruneRemoved is false, we must still retain the record
for (; i < len; i++) {
selection = oldSelections[i];
if (store.indexOf(selection) !== -1) {

// Selected records no longer represented in Store must be retained
else if (!me.pruneRemoved) {
// See if a record by the same ID exists. If so, select it
rec = store.getById(selection.getId());
if (rec) {
// If it does not exist, we have to re-add it to the selection
else {

// In single select mode, only one record may be selected
if (me.mode === 'SINGLE' && toBeReAdded.length) {

// there was a change from the old selected and
// the new selection
if (me.selected.getCount() != (toBeSelected.length + toBeReAdded.length)) {
change = true;

// ADDED - @422 remove our temp fix from above.
delete store.data.useLinearSearch


if (store.indexOf(lastFocused) !== -1) {
// restore the last focus but supress restoring focus
me.setLastFocused(lastFocused, true);

if (toBeSelected.length) {
// perform the selection again
me.doSelect(toBeSelected, false, true);

// If some of the selections were not present in the Store, but pruneRemoved is false, we must add them back
if (toBeReAdded.length) {

// No records reselected.
if (!me.lastSelected) {
me.lastSelected = toBeReAdded[toBeReAdded.length - 1];


16 Dec 2013, 10:19 AM
Thanks for the help. It does look like the issue is the useLinearSearch in the indexOf method.
It may be my situation is slightly different. It is after adding the new record and saving it (i.e. record A) and it updates the id property. When you select a different record on the grid (record B ), record A is not removed from the 'selected' property in the selection model. So when you try to select record A again on the grid, it doesn't get 'selected' because it thinks it's already selected.

I had to override the constuctor instead of the refresh in the Ext.selection.model

constructor: function (cfg) { var me = this;

cfg = cfg || {};
Ext.apply(me, cfg);

* @event
* Fired after a selection change has occurred
* @param {Ext.selection.Model} this
* @param {Ext.data.Model[]} selected The selected records
* @event
* Fired when a row is focused
* @param {Ext.selection.Model} this
* @param {Ext.data.Model} oldFocused The previously focused record
* @param {Ext.data.Model} newFocused The newly focused record

me.modes = {
SINGLE: true,
SIMPLE: true,
MULTI: true

// sets this.selectionMode
me.setSelectionMode(cfg.mode || me.mode);

// maintains the currently selected records.
me.selected = new Ext.util.MixedCollection(null, me.getSelectionId);

//Tempoary fix
me.selected.useLinearSearch = true;


16 Dec 2013, 10:27 AM
Thanks for the response. I wrote my own grid save because we didn't have the time to rewrite our middle tier. I'll add this to my internal documentation.