I use ExtJs GridPanel extensively both for displaying tabular information as well as for data entry. Data entry with GridPanel is mostly a pain in the neck due to navigation issues between cells.
You can use Tab/Shift+Tab for moving between adjacent cells. This works fine in ExtJs 3.x, but has issues in ExtJs 2.x and earlier. Moreover, you need to use mouse for moving between rows, and adding new rows.
So, I created a plugin for making such navigation easy. Tab/Arrow keys mostly are handled by the ExtJs framework. This plugin uses Ctrl+Arrow keys for navigation.
- Ctrl + Left takes you to the left cell. If you are on the first cell of the row, it takes you to the last cell of previous row.
- Ctrl + Right takes you to the right cell. If you are on the last cell of the row, it takes you to the first cell of the next row. If you are already on the last cell of the last row, it add a new row to the GridPanel, and starts editing the first cell of the new row.
- Ctrl + Up takes you to the row above the current row.
- Ctrl + Down takes you to the row below to the current row.
Without further discussion, here’s the javascript for the plugin.
{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }Rahul.ux.EditableGridPanel = function(config) {
Ext.apply(this, config);
};
// plugin code
Ext.extend(Rahul.ux.EditableGridPanel, Ext.util.Observable, {
init: function(grid) {
Ext.apply(grid, {
onRender: grid.onRender.createSequence(function(ct, position) {
var columns = this.colModel.config;
for (i = 0; i < columns.length; i++) {
if (columns[i].editor) {
columns[i].editor.addListener(‘specialkey’, this.gridEditorCtrlArrowKey, this);
}
}
}), // end of function onRender
gridEditorCtrlArrowKey: function(combo, el) {
if (el.keyCode == el.RIGHT || el.keyCode == el.LEFT || el.keyCode == el.UP || el.keyCode == el.DOWN) {
//Make sure Ctrl is pressed to avoid shifting of focus just on the Right or Left arrow key.
if (!el.ctrlKey)
return;
// } else if (el.keyCode == el.TAB) {
// if (el.shiftKey)
// return;
} else
return;
var grd = this;
var row = grd.activeEditor.row;
var col = grd.activeEditor.col;
var totalCols = grd.colModel.config.length;
var totalRows = grd.view.getRows().length;
switch (el.keyCode) {
case el.TAB:
case el.RIGHT:
var next = this.nextEditableCell(row, col);
if (next.isNew)
this.addEditableRow(grd, next.col);
else
grd.startEditing(next.row, next.col);
break;
case el.LEFT:
var prev = this.previousEditableCell(row, col);
if (prev.move)
grd.startEditing(prev.row, prev.col);
break;
case el.UP:
if (row != 0)
grd.startEditing(row – 1, col);
break;
case el.DOWN:
if (row != totalRows – 1)
grd.startEditing(row + 1, col);
break;
}
el.stopEvent();
}, // end of function gridEditorCtrlArrowKey
addEditableRow: function(grd, focusCol) {
var rowIndex = grd.addRecord();
grd.getView().focusRow(rowIndex);
grd.startEditing(rowIndex, focusCol);
},
nextEditableCell: function(row, col) {
var next = {};
for (i = col + 1; i < this.colModel.config.length; i++) {
if (!this.colModel.config[i].hidden) {
next.col = i;
break;
}
}
if (next.col != undefined) {
next.row = row;
next.isNew = false;
} else {
for (i = 0; i < this.colModel.config.length; i++) {
if (!this.colModel.config[i].hidden) {
next.col = i;
break;
}
}
next.row = row + 1;
next.isNew = true;
}
return (next);
},
previousEditableCell: function(row, col) {
var prev = {};
for (i = col – 1; i >= 0; i–) {
if (!this.colModel.config[i].hidden) {
prev.col = i;
break;
}
}
if (prev.col != undefined) {
prev.row = row;
prev.move = true;
} else if (row > 0) {
for (i = this.colModel.config.length – 1; i >= 0; i–) {
if (!this.colModel.config[i].hidden) {
prev.col = i;
prev.row = row – 1;
prev.move = true;
break;
}
}
} else {
prev.row = row;
prev.col = col;
prev.move = false;
}
return (prev);
}
});
} // end of function init
}); // end of extend{/syntaxhighlighter}
Next, if you are using Coolite 0.8.x or earlier, you can use the following server control, that would enable you to embed the above plugin in the <Plugins> inner property of <ext:GridPanel> in markup:
<ToolboxItem(False)> _ <InstanceOf(ClassName:="EditableGridPanel")> _ Public Class EditableGridPanel Inherits Plugin End Class
If you are using Ext.Net 1.x or later, use the following:
{syntaxhighlighter brush: csharp;fontsize: 100; first-line: 1; }[ToolboxItem(false)]
public class EditableGridPanel:Ext.Net.Plugin
{
public override string InstanceOf
{
get
{
return “EditableGridPanel”;
}
}
}{/syntaxhighlighter}
Be sure to include the js file containing the above script in the page also.
The above scrip is flexible enough to automatically ignore columns that do not have an editor attached to them, or hidden columns.
Hei Rahul,
This looks interesting….
I have some questions:
1.
I don’t see how you use Ext.extend(superclass, overrides), with only 2 arguments. You pass in 3 arguments, and don’t use the return value. Is that doing the same?
2.
How to use this? I’m not a Coolite or Ext.Net user… I tried var myEditGrid = new Rahul.ux.EditableGridPanel({…}), but that doesn’t work. Not surprisingly, because your EditableGridPanel extends from Observable, not from EditorGridPanel. Should I first create a standard EditorGridPanel and pass that into your EditableGridPanel constructor? How?
Many thanks…
Martijn
Hi Rahul,
Thanks, that clarifies a lot. learning every day!
Martijn
Dear Rahul:
In this implementation, the used method addRecord (at line 067) is not part of the standard ExtJs3.4 ‘s editorGridPanel. So is a customized method?
Regards.
Hi Rahul, congratulations for your plugin, but I have a problem when I holding the key UP or DOWN + CTRL, the focus of the next cell is lost !!
Any idea?
thanks
I using EXTJS 3.4 and GridEditor component.
Hi rahul,can u plz send me the detailed example that how to use ur plugin in extjs grid.
Thanks in advance.
Hi Rahul,
i am working with extjs 3.4, i have a editor grid panel but unless one condition is satisfied the cells are editable(like if my solution is in first stage then my cells are editable other than the first stage those are not editable). I mean to say that almost my grid cells are not editable. I implemented keyboard navigation for those cells like keydown,keyup,left,right. Now i want to enable tab key navigation too for my grid cells but i am not able to do so, can u send me some solution for enabling tab key pressing.
hi rahul,
i have to fill in some data from a vbnet application to an extjs gridpanel (in a sencha web application) embedded in our vb net application in a ms-webbrowser component.
our aim is; instead of forcing user to enter each row by hand send existing row data to the gridpanel automatically without considering its databind.
how to do that, need your kind help…
best regards
tarik salt
Hi rahul,
i m using ext-3.4 , editable grid, of which only certain cells are editable(clickable) based on some condition. but when i navigate through tab/shift tab, the focus moves also on to those cells which are not fullfilling those condition although mouse-click is restricted.
so how to restrict tab/shift tab navigation on those cells
Is this compatible with ExtJs 4.2? I am upgrading an application and this is one feature that i am currently missing.