16

I have a problem. I use extjs grid. This grid will be refreshed every seconds.

I refresh with this function:

ND.refresh = function() {
    ND.commList.load();
}


var refreshSeconds = refreshRate * 1000;
var t = setInterval('ND.refresh()', refreshSeconds);

But when someone selected a row to highlight it it reset this selection. How can I remember the selected row and highlight it again after refresh?

This is my grid:

var grid = Ext.create('Ext.grid.Panel', {
     autoscroll: true,
     region: 'center',
     store: ND.dashBoardDataStore,
     stateful: true,
     forceFit: true,
     loadMask: false,
     stateId: 'stateGrid',

     viewConfig: {
         stripeRows: true
     },
     columns: [{
         text: 'Vehicle',
         sortable: true,
         flexible: 1,
         width: 60,
         dataIndex: 'vehicle'
     }, {
         text: 'CCU',
         sortable: true,
         flexible: 0,
         width: 50,
         renderer: status,
         dataIndex: 'ccuStatus'
     }]
 });

Thanks guys

Narendra Jadhav
  • 10,052
  • 15
  • 33
  • 44
Rick Weller
  • 1,258
  • 9
  • 35
  • 54
  • What version of Ext do you use? Test code (in [JsFiddle](http://jsfiddle.net/)) would be nice so we have a starting point to help you in a best possible way. – sbgoran Feb 02 '12 at 11:51
  • Thanks for your reply. I use EXT 4.0.2. i don't know fiddle. How do i need to put it in there? – Rick Weller Feb 02 '12 at 12:06

5 Answers5

20

I wrote simple Ext.grid.Panel extension that automatically selects back rows that were selected before store reload. You can try it in this jsFiddle

Ext.define('PersistantSelectionGridPanel', {
    extend: 'Ext.grid.Panel',
    selectedRecords: [],
    initComponent: function() {
        this.callParent(arguments);

        this.getStore().on('beforeload', this.rememberSelection, this);
        this.getView().on('refresh', this.refreshSelection, this);
    },
    rememberSelection: function(selModel, selectedRecords) {
        if (!this.rendered || Ext.isEmpty(this.el)) {
            return;
        }

        this.selectedRecords = this.getSelectionModel().getSelection();
        this.getView().saveScrollState();
    },
    refreshSelection: function() {
        if (0 >= this.selectedRecords.length) {
            return;
        }

        var newRecordsToSelect = [];
        for (var i = 0; i < this.selectedRecords.length; i++) {
            record = this.getStore().getById(this.selectedRecords[i].getId());
            if (!Ext.isEmpty(record)) {
                newRecordsToSelect.push(record);
            }
        }

        this.getSelectionModel().select(newRecordsToSelect);
        Ext.defer(this.setScrollTop, 30, this, [this.getView().scrollState.top]);
    }
});
sbgoran
  • 3,451
  • 2
  • 19
  • 30
  • 1
    hey looking good. I have only two issues. In firefox i get this error: this.selectedRecords[i].getId is not a function. When i use it in chrome it will always select the first row after refresh. Any idea what that could be? THANKS for the help :) – Rick Weller Feb 06 '12 at 07:20
  • 1
    the error in firefox is fixed. But it is still going to the first row – Rick Weller Feb 06 '12 at 08:44
  • 1
    http://jsfiddle.net/ZemWB/ is where i placed my grid with your code. Can you see what is wrong with it? – Rick Weller Feb 06 '12 at 10:43
  • First of all in that jsFiddle you created `ND` is undefined. I guess you copy/paste code from your project but it is not runnable. I guess you could have issues if you haven't set `idProperty` in your model (look at [my test fiddle](http://jsfiddle.net/sbgoran/A2H5r/)) – sbgoran Feb 06 '12 at 11:58
  • You are my hero! I didn't had a idProperty in my model. Thanks thanks thanks – Rick Weller Feb 06 '12 at 12:03
  • I have no another issue :) I got a list higher then the screen, if i scroll down, select a row the row will stay selected but after refresh it scrolls back up. Can i do something about that? – Rick Weller Feb 06 '12 at 12:22
  • Well you could try something with [Ext.view.Table.saveScrollState](http://docs.sencha.com/ext-js/4-0/#!/api/Ext.view.Table-method-saveScrollState) method and [Ext.grid.Panel.setScrollTop](http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.Panel-method-setScrollTop) method. You can fetch view object of a grid panel with [Ext.grid.Panel.getView](http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.Panel-method-getView) method. Of course use appropriate methods in `rememberSelection` and `refreshSelection` methods of a custom extension. – sbgoran Feb 07 '12 at 12:02
  • I updated code in answer, so now panel set vertical scroll to its previous value. You can play with solution in that fiddle. – sbgoran Feb 08 '12 at 13:28
  • hey Sbgoran. There is an issue what i can't fix. When the page loads i get an error this.el is undefined and isn't loading the store. When the refresh function start it loads the store. I tried to remove this code and store loads fine. Do you have an idea what this.el could be? – Rick Weller Feb 10 '12 at 13:41
  • I really don't know what is wrong in your code, but I added a check in `rememberSelection` that shouldn't do any harm, try it out, it might help. – sbgoran Feb 10 '12 at 14:24
  • 2
    This is great but it should be a plugin, not a base class! – Ruan Mendes May 30 '12 at 22:46
  • 1
    @JuanMendes You are probably right, but I guess that answer shows the main idea for solution to a problem it should not be very hard to make plugin out of this. Maybe I'll do it when I get a chance, should be fun thing to do :) – sbgoran Jun 01 '12 at 08:01
  • @comecme It was a while ago, so if I remember well reason lays in a way Ext grid render its view, I think that they used defer call during grid panel rendering inside library itself, so if you call `setScrollTop` immediately, you'll get some sort of "null variable" or "non existent DOM element" error. It could be that later versions of Ext removed this and that it is not necessary anymore. – sbgoran Mar 13 '14 at 08:45
7

The straightforward solution is just save somewhere in js index of selected row. Then after reload you could easily select this row by index using grid's selection model.

Get selection model: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.Panel-method-getSelectionModel

var selectionModel = grid.getSelectionModel()

Get selected rows: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.selection.Model-method-getSelection

var selection = selectionModel.getSelection()

Set selected row back: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.selection.Model-method-select

selectionModel.select(selection)
Andrey Selitsky
  • 2,584
  • 3
  • 28
  • 42
  • i think i do something wrong because it isnt working. i use a listener: itemclick: function () { var selectionModel = grid.getSelectionModel(); var selection = selectionModel.getSelection(); selectionModel.select(selection); var data = grid.getSelectionModel().selected.items[0].data; ND.internals.load({ url: ND.url }); – Rick Weller Feb 02 '12 at 13:06
  • you should restore selection after your reloading is completed. So it's a good idea call selectionModel.select in grid's store load event. – Andrey Selitsky Feb 02 '12 at 13:34
4

Here is another way to select the previously selected record:

var selectionModel = grid.getSelectionModel()

// get the selected record
var selectedRecord = selectionModel.getSelection()[0]

// get the index of the selected record
var selectedIdx = grid.store.indexOfId(selectedRecord.data.id);

// select by index
grid.getSelectionModel().select(selectedIdx);

For some reason the grid.getSelectionModel().select(record) method wasn't working for me, but selecting by index seems to work.

Edit: found out why grid.getSelectionModel().select(record) method wasn't working. Apparently the store is reloaded, the record instances aren't the same (they have different automatically generated Ext IDs). You have to use selectAt() in this case.

Sasha Brocato
  • 673
  • 10
  • 14
1

for extjs 4.1.7 users

need a workarround about the statement in

refreshSelection() {

...
Ext.defer(this.setScrollTop, 30, this, [this.getView().scrollState.top])

}

thus setScrollTop no longer exists

so a working soluction is add me.getView().preserveScrollOnRefresh = true;

in initComponent

Ext.define('PersistantSelectionGridPanel', {
    extend: 'Ext.grid.Panel',
    selectedRecords: [],
    initComponent: function() {
        this.callParent(arguments);

        this.getStore().on('beforeload', this.rememberSelection, this);
        this.getView().on('refresh', this.refreshSelection, this);

        //-------------------------------------------
        me.getView().preserveScrollOnRefresh = true;
        //-------------------------------------------
    },
    rememberSelection: function(selModel, selectedRecords) {
        if (!this.rendered || Ext.isEmpty(this.el)) {
            return;
        }

        this.selectedRecords = this.getSelectionModel().getSelection();
        this.getView().saveScrollState();
    },
    refreshSelection: function() {
        if (0 >= this.selectedRecords.length) {
            return;
        }

        var newRecordsToSelect = [];
        for (var i = 0; i < this.selectedRecords.length; i++) {
            record = this.getStore().getById(this.selectedRecords[i].getId());
            if (!Ext.isEmpty(record)) {
                newRecordsToSelect.push(record);
            }
        }

        this.getSelectionModel().select(newRecordsToSelect);
    }
});
PMargarido
  • 41
  • 2
0

i have make modification on this code. If you make selection, and aplys a filter on the store and reload it, the selection model have a first empty array in this selected collection ( at index 0 ).

This modification is in the last line of the "refreshSelection" function.

if (newRecordsToSelect.length >= 1){
        this.getSelectionModel().select(newRecordsToSelect);
        Ext.defer(this.setScrollTop, 30, this, [this.getView().scrollState.top]);
    }
Pixman
  • 599
  • 6
  • 17