Sunday, February 08, 2009

ExtJS Tip : Sortable Grid Rows via Drag and Drop

One particular challenge on a recent project is to have the ability to sort grid rows using drag and drop. With lots of help from the ExtJS forums, here's how I ended up doing it.

The code snippet below shows an Ext gridpanel with the added ability to allow users to sort rows using drag and drop. This is acheived by (1) setting the enableDragDrop configuration to true to allow dragging and dropping of rows and (2) creating a drop target that handles the drop event when a row is dropped.

Update 031609 : An anonymous comment mentioned having problems with sorting multiple rows. This tip only works with single select rows. I have added the code change below that forces the grid to use a single select row selection model.



var grid = new Ext.grid.GridPanel({
id: 'mygrid',
title: 'My Grid',
store: store, // define the data store in a separate variable
loadMask: true,
ddGroup:'mygridDD',
enableDragDrop: true, // enable drag and drop of grid rows
viewConfig: {
emptyText: 'No pages found',
sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
forceFit: true
}, columns: gridcolumns, // define grid columns in a separate variable
listeners: {
"render": {
scope: this,
fn: function(grid) {

// Enable sorting Rows via Drag & Drop
// this drop target listens for a row drop
// and handles rearranging the rows

var ddrow = new Ext.dd.DropTarget(grid.container, {
ddGroup : 'mygridDD',
copy:false,
notifyDrop : function(dd, e, data){

var ds = grid.store;

// NOTE:
// you may need to make an ajax call here
// to send the new order
// and then reload the store



// alternatively, you can handle the changes
// in the order of the row as demonstrated below

// ***************************************

var sm = grid.getSelectionModel();
var rows = sm.getSelections();
if(dd.getDragData(e)) {
var cindex=dd.getDragData(e).rowIndex;
if(typeof(cindex) != "undefined") {
for(i = 0; i < rows.length; i++) {
ds.remove(ds.getById(rows[i].id));

}
ds.insert(cindex,data.selections);
sm.clearSelections();
}
}

// ************************************
}
})

// load the grid store
// after the grid has been rendered
store.load();
}

}
}
})