-
1 Sep 2009 5:09 AM #1Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 40
EditableGrid - Shows editors for all cells
EditableGrid - Shows editors for all cells
EditorGridPanel only supports one editor for each column and the editor is only shown after single or double clicking the cell.
EditorGridPanel is not designed to show editors on every cell, because this would make the browser extremely slow with large datasets.
I created this plugin to show editors for all cells in a GridPanel (so not an EditorGridPanel!).
As noted above: Do NOT use this plugin for large datasets!
The plugin:
which requires the following css rule:Code:Ext.ns('Ext.ux.grid'); Ext.ux.grid.EditableGrid = Ext.extend(Object, { init : function(grid){ Ext.apply(grid.getView(), { editors: [], editorPadding: 2, renderUI : function(){ this.constructor.prototype.renderUI.call(this); this.el.addClass('x-grid-editing'); }, updateAllColumnWidths : function(){ this.constructor.prototype.updateAllColumnWidths.call(this); var editors = this.editors, rows = editors.length, cols = this.cm.getColumnCount(), col, row, ed, w = []; for(col = 0; col < cols; col++){ w[col] = this.cm.getColumnWidth(col) - this.editorPadding; } for(row = 0; row < rows; row++){ for(col = 0; col < cols; col++){ ed = editors[row][col]; if(ed){ ed.setWidth(w[col]); } } } }, updateColumnWidth : function(col, width){ this.constructor.prototype.updateColumnWidth.call(this, col, width); var editors = this.editors, rows = editors.length, row, ed, w = this.cm.getColumnWidth(col) - this.editorPadding; for(row = 0; row < rows; row++){ ed = editors[row][col]; if(ed){ ed.setWidth(w); } } }, afterRender : function(){ this.constructor.prototype.afterRender.call(this); this.destroyAllEditors(); this.renderEditors(0, this.ds.getCount() - 1); }, insertRows : function(dm, firstRow, lastRow, isUpdate){ this.constructor.prototype.insertRows.call(this, dm, firstRow, lastRow, isUpdate); var last = dm.getCount() - 1; if(!isUpdate && firstRow === 0 && lastRow >= last){ return; } this.renderEditors(firstRow, lastRow); }, deleteRows : function(dm, firstRow, lastRow){ if(dm.getRowCount() >= 1){ this.destroyEditors(firstRow, lastRow); } this.constructor.prototype.deleteRows.call(this, dm, firstRow, lastRow); }, refreshRow : function(record){ var ds = this.ds, index; if(typeof record == 'number'){ index = record; record = ds.getAt(index); if(!record){ return; } }else{ index = ds.indexOf(record); if(index < 0){ return; } } this.destroyEditors(index, index); this.constructor.prototype.refreshRow.call(this, record); this.renderEditors(index, index); }, refresh : function(headersToo){ this.destroyAllEditors(); this.constructor.prototype.refresh.call(this, headersToo); this.renderEditors(0, this.ds.getCount() - 1); }, destroy : function(){ this.destroyAllEditors(); this.constructor.prototype.destroy.call(this); }, focusCell : function(row, col, hscroll){ this.syncFocusEl(this.ensureVisible(row, col, hscroll)); var ed = this.editors[row][col], focusEl = ed ? ed : this.focusEl; if(Ext.isGecko){ focusEl.focus(); }else{ focusEl.focus.defer(1, this.focusEl); } }, renderEditors: function(startRow, endRow){ var args = [startRow, 0], cols = this.cm.getColumnCount(), col, row, ed, w = [], rec, r, di, cell; for(col = 0; col < cols; col++){ w[col] = this.cm.getColumnWidth(col) - this.editorPadding; } for(row = startRow; row <= endRow; row++){ r = []; rec = this.ds.getAt(row); for(col = 0; col < cols; col++){ ed = this.cm.isCellEditable(col, row) ? this.cm.getCellEditor(col, row) : null; if(ed){ cell = this.getCell(row, col).firstChild; cell.parentNode.removeAttribute('tabindex'); cell.innerHTML = ''; di = this.cm.getDataIndex(col); ed = ed.field.cloneConfig({ value: rec.get(di), width: w[col], renderTo: cell, ctCls: 'x-small-editor x-grid-editor ux-editable-grid' }); ed.on('blur', this.onEditorBlur, { store: this.ds, row: row, dataIndex: di }); } r.push(ed); } args.push(r); } this.editors.splice.apply(this.editors, args); }, destroyEditors: function(startRow, endRow){ var removed = this.editors.splice(startRow, endRow - startRow + 1); Ext.destroy(removed); }, destroyAllEditors: function(){ Ext.destroy(this.editors); this.editors = []; }, onEditorBlur: function(field){ this.store.getAt(this.row).data[this.dataIndex] = field.getValue(); } }); } }); Ext.preg('editable-grid', Ext.ux.grid.EditableGrid);
Usage example:Code:.ux-editable-grid { padding: 0; }
Code:Ext.onReady(function(){ Ext.QuickTips.init(); new Ext.grid.GridPanel({ title: 'EditableGrid plugin test', width: 250, height: 150, store: [[1, 'One'], [2, 'Two'], [3, 'Three'], [4, 'Four'], [5, 'Five']], viewConfig: { forceFit: true }, columns: [{ header: 'Value', dataIndex: 'field1', editor: { xtype: 'numberfield', minValue: 0, maxValue: 100 } },{ header: 'Text', dataIndex: 'field2', editor: { xtype: 'textfield', allowBlank: false } }], plugins: [{ ptype: 'editable-grid' }], renderTo: Ext.getBody() }); });
-
1 Sep 2009 10:09 AM #2
there might still be a way to cheat and use 1 editor per column...
what if we style all the inputs to look like textfields, but move/show/hide the column editor the way the editorgridpanel does. would that help to reduce the overhead of per-cell component creation?
Sencha Docs / Ext 3.x - ( Docs | Examples )
Learning Center / Saki's Examples (for 2.x) / HOWTO - ( Report Bugs | Post Proper Code )
-
1 Sep 2009 10:25 AM #3Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 40
A few problems with that solution:
1. You would have to create a specific renderer for every editor type so the cell looks like the editor. The list of renderer should be extendable to support form field extensions.
3. A mouse down on a cell would move the editor to that cell, but the mouse down event would not be forwarded to the field (which could mean that a second click is required to actually use the field).
-
1 Sep 2009 7:36 PM #4
Great plugin.
Can this plug-in be used to display editors not to ALL cells?
-
1 Sep 2009 9:56 PM #5
-
2 Sep 2009 2:16 PM #6
Hi Condor,
I accidentally saw this plugin while I was struggling to show slider in EditorGridPanel. Actually I was waiting your reply to this post, which was about the same problem. This is what I need and slider renders perfectly!
But I'm still gonna insist on using this plugin for EditorGridPanel
I understand that using this kind of feature on EditorGridPanel with a large dataset will slow down the browser but as I said in the above mentioned post, the dataset that I'm gonna use will have 5-6 records at max. So I believe I won't have any performance problems. And since I only need one column (the one that will be using the slider as an editor) to show the slider at all times, I changed your renderEditors method in order to do rendering if there is an 'alwaysShowEditor' option with "true" value for the column config. So even though the column has an editor, editor won't be rendered unless the alwaysShowEditor === true, so this will also help performance.
Is there a possibility to have this plugin work also for EditorGridPanel?
Thanks in advance
-
2 Sep 2009 3:21 PM #7
Hi Condor,
I tried to use the plugin for EditorGridPanel and made it work by using the previously mentioned "alwaysShowEditor"option. In my extended EditorGridPanel, I've overridden the startEditing prototype method and prevented it to work for columns that have alwaysShowEditor === true.
So far it's working without a problem but since I'm not that much into inner workings of Ext JS, I wanted to ask if this is enough.
Thanks
-
2 Sep 2009 9:26 PM #8Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 40
Yes, that should do it.
ps. Does your slider control fire the required 'blur' event?
-
3 Sep 2009 1:17 AM #9
No, I've only copied the necessary Ext.form.Field prototype methods to Ext.Slider in order to be able to use it as an editor in EditorGridPanel. And as much as I've seen it doesn't fire 'blur' event.
I've checked out your plugin and if I'm not wrong without the blur event the value on slider will not be written back to store? Am I correct?
Is it easy to add blur event to slider?
Thanks
-
3 Sep 2009 3:17 AM #10Sencha - Community Support Team
- Join Date
- Mar 2007
- Location
- The Netherlands
- Posts
- 24,251
- Vote Rating
- 40
To be compatible with Ext.form.Field, you should attach a blur event handler to the focusEl element and fire a change and a blur event on the component.


Reply With Quote