GWT-EXT: Retain Checkbox selections in page-able GridPanel

When working on a sample project for Mersoft using GWT-EXT I came across a use case that required a data table that was page-able, had a checkbox selection per row, and needed to maintain the checkbox selections when paging.

Here is what I ended up doing. It may not be pretty, but hey, its a sample.

I made a few updates to the CheckboxSelectionModel.js in order to properly update the checkbox in the Header row when a user manually (un)selects all the rows. This required that I comment out the CheckboxSelectionModel definition in the ext-all.js and include the CheckboxSelectionModel.js in my HTML. I updated the onMouseDown function as follows…

onMouseDown : function(e, t){
        if(e.button === 0 && t.className == ‘x-grid3-row-checker’){ // Only fire if left-click
            e.stopEvent();
            var row = e.getTarget(‘.x-grid3-row’);
            if(row){
                var index = row.rowIndex;
                if(this.isSelected(index)){
                    this.deselectRow(index);
                }else{
                    this.selectRow(index, true);
                }

                //Get the CheckboxHeader so it can be updated.
               //Loop through the header cells since the user may have re-ordered them…
               var cbHeader = null;
               var i = 0;
               var view = this.grid.getView();
               var headerCellEl = view.getHeaderCell(i);

               while(cbHeader == null && headerCellEl != null){
                  if(headerCellEl.className.indexOf(‘x-grid3-td-checker’) > -1){
                     cbHeader = headerCellEl.firstChild;
                     cbHeader = Ext.fly(cbHeader);
                  }
                  headerCellEl = view.getHeaderCell(++i);
               }

                if (cbHeader) {
                if (this.grid.getStore().getCount() == this.selections.length) {
                   //all the rows are selected, so check the header…
                   cbHeader.addClass(‘x-grid3-hd-checker-on’);
                } else {
                   //not all the rows are selected, so uncheck the header…
                   cbHeader.removeClass(‘x-grid3-hd-checker-on’);
                }
             }
            }
        }
    },

I also used the code from the URL http://extjs.com/forum/showthread.php?t=45723&highlight=getselectionmodel, however it too needed to be modified to update the Header checkbox.

I created a CheckBoxMemory.js with the following code and included it in my HTML…

Ext.namespace(‘Ext.ux.plugins’);

Ext.ux.plugins.CheckBoxMemory = Ext.extend(Object, {
   constructor : function(config) {
      if (!config)
         config = {};

      this.prefix = ‘id_’;
      this.items = {};
      this.idProperty = config.idProperty || ‘id’;
   },

   init : function(grid) {
      this.grid = grid;
      this.view = grid.getView()
      this.store = null;
      this.sm = grid.getSelectionModel();
      this.sm.on(‘rowselect’, this.onSelect, this);
      this.sm.on(‘rowdeselect’, this.onDeselect, this);
      this.view.on(‘refresh’, this.reConfigure, this);
   },

   reConfigure : function() {
      this.store = this.grid.getStore();
      this.store.on(‘clear’, this.onClear, this);
      this.store.on(‘datachanged’, this.restoreState, this);
   },

   onSelect : function(sm, idx, rec) {
      this.items[this.getId(rec)] = true;
   },

   onDeselect : function(sm, idx, rec) {
      delete this.items[this.getId(rec)];
   },

   restoreState : function() {
      if (this.store != null) {
         var i = 0;
         var sel = [];
         this.store.each( function(rec) {
            var id = this.getId(rec);
            if (this.items[id] === true)
               sel.push(i);

            ++i;
         }, this);
         if (sel.length > 0){

            this.sm.selectRows(sel);
         }

         var cbHeader = null;
         var j = 0;
         var view = this.grid.getView();
         var headerCellEl = view.getHeaderCell(j);

         while (cbHeader == null && headerCellEl != null) {

            if (headerCellEl.className.indexOf(‘x-grid3-td-checker’) > -1) {
               cbHeader = headerCellEl.firstChild;
               cbHeader = Ext.fly(cbHeader);
            }
            headerCellEl = view.getHeaderCell(++j);
         }

         if (cbHeader) {
            if (this.store.getCount() == this.sm.selections.length) {
               cbHeader.addClass(‘x-grid3-hd-checker-on’);
            } else {
               cbHeader.removeClass(‘x-grid3-hd-checker-on’);
            }
         }
      }
   },

   onClear : function() {
      var sel = [];
      this.items = {};
   },

   getId : function(rec) {
      return rec.get(this.idProperty);
   }
});

I have not had a chance to really dive in ,but you will need to make sure that your RecordDef has a FieldDef with a name of “id”, example… new StringFieldDef(”id”, 0)

I then created the corresponding Java class as follows.

package com.mersoft.gwtsample.client.widgets.grid;

import com.google.gwt.core.client.JavaScriptObject;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.ComponentPlugin;

public class CheckBoxMemoryPlugin extends ComponentPlugin {

    public CheckBoxMemoryPlugin() {
        jsObj = create();
    }

    protected native JavaScriptObject create() /*-{
        return new $wnd.Ext.ux.plugins.CheckBoxMemory();
    }-*/
;

    @Override
        public void init(Component component) {
    }
}

Then you just need to add the CheckBoxMemoryPlugin to the GridPanel. (This assumes that you already have set up a Local Paging Checkbox Grid Panel)

grid.addPlugin(new CheckBoxMemoryPlugin());

Anyway, I hope this helps someone else who may be looking to solve this.

I still need to update the code in order to be able to get the selected row IDs, but that is for another day.

  • Share/Bookmark

Leave a Reply

You must be logged in to post a comment.