02 February 2010

ExtJS Helper Functions - SelectionModel Modifications

One of the application patterns I implement in ExtJS is to have ViewPort containing a grid with records for a user to edit.  The user double-clicks a record on the grid, which opens a window to edit the information.  When complete, the user then closes the window and the grid refreshes.

The issue is that after the grid refreshes, the user loses her place on the grid as the selection goes back to the first record.

Additionally, the RowSelectionModel() only implements selection by index, which means that if there are concurrency checks, you cannot automatically go back to the index you were on or guarantee the new index will be correct.

These methods attempt to correct these shortcomings.  The first extension implements a selectById method for the RowSelectionModel object.

The second extension implements a SelectAfterLoad method on the GridPanel (and all of it's descending objects).  When closing the form, take the id from the record you are using and pass it into the selectAfterLoad method.  The method will kick off a single event to find the id in the current loaded record set.  If the id of the record is not found, the default 'selectFirstRow()' method is called.


// extend the RowSelectionModel
Ext.override(Ext.grid.RowSelectionModel, {

// enables the selection model to select by record id
selectById: function (id) {

var sm = this,               // hook to the selection model
      s = sm.grid.store,   // reference to the store
      f = false,                 // found (initialized as false)
      idx = 0;                   // record index

      // if store has no records, return control
      if (s.getCount() === 0) {
          return;
      }

     // iterate through each record, looking for the id
     s.each(function (r) {
          // if the record id matches the passed id
          if (r.id.toString() === id.toString()) {
               // found is true
               f = true;
               // select the row
               sm.selectRow(idx, false);
               // return false to exit
               return !f;
          }


          // iterate the index
          idx = idx + 1;
         // return true to continue iteration
         return !f;
      });
           // if not false, exit
            if (!f) {
                // select the first row
               sm.selectFirstRow();
          }
     }
});

// selects by record id after the grid reloads
Ext.override(Ext.grid.GridPanel, {

     // selects row by id after store loads
     selectAfterLoad: function (id) {

     // get the grid selection model
     var sm = this.getSelectionModel();

     // select record by passed id argument after store loads
     this.store.on({
               'load': {
                     fn: function (t, recs, opts) {
                          sm.selectById(id);
                      },
                      single: true
                 }
           });
      }
});