Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / CellEditing.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-grid.plugin.CellEditing'>/**
2 </span> * @class Ext.grid.plugin.CellEditing
3  * @extends Ext.grid.plugin.Editing
4  *
5  * The Ext.grid.plugin.CellEditing plugin injects editing at a cell level for a Grid. Only a single
6  * cell will be editable at a time. The field that will be used for the editor is defined at the
7  * {@link Ext.grid.column.Column#field field}. The editor can be a field instance or a field configuration.
8  *
9  * If an editor is not specified for a particular column then that cell will not be editable and it will
10  * be skipped when activated via the mouse or the keyboard.
11  *
12  * The editor may be shared for each column in the grid, or a different one may be specified for each column.
13  * An appropriate field type should be chosen to match the data structure that it will be editing. For example,
14  * to edit a date, it would be useful to specify {@link Ext.form.field.Date} as the editor.
15  *
16  * {@img Ext.grid.plugin.CellEditing/Ext.grid.plugin.CellEditing.png Ext.grid.plugin.CellEditing plugin}
17  *
18  * ## Example Usage
19  *
20  *     Ext.create('Ext.data.Store', {
21  *         storeId:'simpsonsStore',
22  *         fields:['name', 'email', 'phone'],
23  *         data:{'items':[
24  *             {&quot;name&quot;:&quot;Lisa&quot;, &quot;email&quot;:&quot;lisa@simpsons.com&quot;, &quot;phone&quot;:&quot;555-111-1224&quot;},
25  *             {&quot;name&quot;:&quot;Bart&quot;, &quot;email&quot;:&quot;bart@simpsons.com&quot;, &quot;phone&quot;:&quot;555--222-1234&quot;},
26  *             {&quot;name&quot;:&quot;Homer&quot;, &quot;email&quot;:&quot;home@simpsons.com&quot;, &quot;phone&quot;:&quot;555-222-1244&quot;},
27  *             {&quot;name&quot;:&quot;Marge&quot;, &quot;email&quot;:&quot;marge@simpsons.com&quot;, &quot;phone&quot;:&quot;555-222-1254&quot;}
28  *         ]},
29  *         proxy: {
30  *             type: 'memory',
31  *             reader: {
32  *                 type: 'json',
33  *                 root: 'items'
34  *             }
35  *         }
36  *     });
37  *     
38  *     Ext.create('Ext.grid.Panel', {
39  *         title: 'Simpsons',
40  *         store: Ext.data.StoreManager.lookup('simpsonsStore'),
41  *         columns: [
42  *             {header: 'Name',  dataIndex: 'name', field: 'textfield'},
43  *             {header: 'Email', dataIndex: 'email', flex:1,
44  *                 editor: {
45  *                     xtype:'textfield',
46  *                     allowBlank:false
47  *                 }
48  *             },
49  *             {header: 'Phone', dataIndex: 'phone'}
50  *         ],
51  *         selType: 'cellmodel',
52  *         plugins: [
53  *             Ext.create('Ext.grid.plugin.CellEditing', {
54  *                 clicksToEdit: 1
55  *             })
56  *         ],
57  *         height: 200,
58  *         width: 400,
59  *         renderTo: Ext.getBody()
60  *     });
61  */
62 Ext.define('Ext.grid.plugin.CellEditing', {
63     alias: 'plugin.cellediting',
64     extend: 'Ext.grid.plugin.Editing',
65     requires: ['Ext.grid.CellEditor'],
66
67     constructor: function() {
68 <span id='Ext-grid.plugin.CellEditing-event-beforeedit'>        /**
69 </span>         * @event beforeedit
70          * Fires before cell editing is triggered. The edit event object has the following properties &lt;br /&gt;
71          * &lt;ul style=&quot;padding:5px;padding-left:16px;&quot;&gt;
72          * &lt;li&gt;grid - The grid&lt;/li&gt;
73          * &lt;li&gt;record - The record being edited&lt;/li&gt;
74          * &lt;li&gt;field - The field name being edited&lt;/li&gt;
75          * &lt;li&gt;value - The value for the field being edited.&lt;/li&gt;
76          * &lt;li&gt;row - The grid table row&lt;/li&gt;
77          * &lt;li&gt;column - The grid {@link Ext.grid.column.Column Column} defining the column that is being edited.&lt;/li&gt;
78          * &lt;li&gt;rowIdx - The row index that is being edited&lt;/li&gt;
79          * &lt;li&gt;colIdx - The column index that is being edited&lt;/li&gt;
80          * &lt;li&gt;cancel - Set this to true to cancel the edit or return false from your handler.&lt;/li&gt;
81          * &lt;/ul&gt;
82          * @param {Ext.grid.plugin.Editing} editor
83          * @param {Object} e An edit event (see above for description)
84          */
85 <span id='Ext-grid.plugin.CellEditing-event-edit'>        /**
86 </span>         * @event edit
87          * Fires after a cell is edited. The edit event object has the following properties &lt;br /&gt;
88          * &lt;ul style=&quot;padding:5px;padding-left:16px;&quot;&gt;
89          * &lt;li&gt;grid - The grid&lt;/li&gt;
90          * &lt;li&gt;record - The record that was edited&lt;/li&gt;
91          * &lt;li&gt;field - The field name that was edited&lt;/li&gt;
92          * &lt;li&gt;value - The value being set&lt;/li&gt;
93          * &lt;li&gt;originalValue - The original value for the field, before the edit.&lt;/li&gt;
94          * &lt;li&gt;row - The grid table row&lt;/li&gt;
95          * &lt;li&gt;column - The grid {@link Ext.grid.column.Column Column} defining the column that was edited.&lt;/li&gt;
96          * &lt;li&gt;rowIdx - The row index that was edited&lt;/li&gt;
97          * &lt;li&gt;colIdx - The column index that was edited&lt;/li&gt;
98          * &lt;/ul&gt;
99          *
100          * &lt;pre&gt;&lt;code&gt;
101 grid.on('edit', onEdit, this);
102
103 function onEdit(e) {
104     // execute an XHR to send/commit data to the server, in callback do (if successful):
105     e.record.commit();
106 };
107          * &lt;/code&gt;&lt;/pre&gt;
108          * @param {Ext.grid.plugin.Editing} editor
109          * @param {Object} e An edit event (see above for description)
110          */
111 <span id='Ext-grid.plugin.CellEditing-event-validateedit'>        /**
112 </span>         * @event validateedit
113          * Fires after a cell is edited, but before the value is set in the record. Return false
114          * to cancel the change. The edit event object has the following properties &lt;br /&gt;
115          * &lt;ul style=&quot;padding:5px;padding-left:16px;&quot;&gt;
116          * &lt;li&gt;grid - The grid&lt;/li&gt;
117          * &lt;li&gt;record - The record being edited&lt;/li&gt;
118          * &lt;li&gt;field - The field name being edited&lt;/li&gt;
119          * &lt;li&gt;value - The value being set&lt;/li&gt;
120          * &lt;li&gt;originalValue - The original value for the field, before the edit.&lt;/li&gt;
121          * &lt;li&gt;row - The grid table row&lt;/li&gt;
122          * &lt;li&gt;column - The grid {@link Ext.grid.column.Column Column} defining the column that is being edited.&lt;/li&gt;
123          * &lt;li&gt;rowIdx - The row index that is being edited&lt;/li&gt;
124          * &lt;li&gt;colIdx - The column index that is being edited&lt;/li&gt;
125          * &lt;li&gt;cancel - Set this to true to cancel the edit or return false from your handler.&lt;/li&gt;
126          * &lt;/ul&gt;
127          * Usage example showing how to remove the red triangle (dirty record indicator) from some
128          * records (not all).  By observing the grid's validateedit event, it can be cancelled if
129          * the edit occurs on a targeted row (for example) and then setting the field's new value
130          * in the Record directly:
131          * &lt;pre&gt;&lt;code&gt;
132 grid.on('validateedit', function(e) {
133   var myTargetRow = 6;
134
135   if (e.row == myTargetRow) {
136     e.cancel = true;
137     e.record.data[e.field] = e.value;
138   }
139 });
140          * &lt;/code&gt;&lt;/pre&gt;
141          * @param {Ext.grid.plugin.Editing} editor
142          * @param {Object} e An edit event (see above for description)
143          */
144         this.callParent(arguments);
145         this.editors = Ext.create('Ext.util.MixedCollection', false, function(editor) {
146             return editor.editorId;
147         });
148     },
149
150 <span id='Ext-grid.plugin.CellEditing-method-destroy'>    /**
151 </span>     * @private
152      * AbstractComponent calls destroy on all its plugins at destroy time.
153      */
154     destroy: function() {
155         var me = this;
156         me.editors.each(Ext.destroy, Ext);
157         me.editors.clear();
158         me.callParent(arguments);
159     },
160
161     // private
162     // Template method called from base class's initEvents
163     initCancelTriggers: function() {
164         var me   = this;
165             grid = me.grid,
166             view   = grid.view;
167
168         me.mon(view, {
169             mousewheel: {
170                 element: 'el',
171                 fn: me.cancelEdit,
172                 scope: me
173             }
174         });
175         me.mon(grid, {
176             columnresize: me.cancelEdit,
177             columnmove: me.cancelEdit,
178             scope: me
179         });
180     },
181
182 <span id='Ext-grid.plugin.CellEditing-method-startEdit'>    /**
183 </span>     * Start editing the specified record, using the specified Column definition to define which field is being edited.
184      * @param {Model} record The Store data record which backs the row to be edited.
185      * @param {Model} columnHeader The Column object defining the column to be edited.
186      * @override
187      */
188     startEdit: function(record, columnHeader) {
189         var me = this,
190             ed   = me.getEditor(record, columnHeader),
191             value = record.get(columnHeader.dataIndex),
192             context = me.getEditingContext(record, columnHeader);
193
194         record = context.record;
195         columnHeader = context.column;
196
197         // Complete the edit now, before getting the editor's target
198         // cell DOM element. Completing the edit causes a view refresh.
199         me.completeEdit();
200
201         // See if the field is editable for the requested record
202         if (columnHeader &amp;&amp; !columnHeader.getEditor(record)) {
203             return false;
204         }
205
206         if (ed) {
207             context.originalValue = context.value = value;
208             if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
209                 return false;
210             }
211
212             me.context = context;
213             me.setActiveEditor(ed);
214             me.setActiveRecord(record);
215             me.setActiveColumn(columnHeader);
216
217             // Defer, so we have some time between view scroll to sync up the editor
218             Ext.defer(ed.startEdit, 15, ed, [me.getCell(record, columnHeader), value]);
219         } else {
220             // BrowserBug: WebKit &amp; IE refuse to focus the element, rather
221             // it will focus it and then immediately focus the body. This
222             // temporary hack works for Webkit and IE6. IE7 and 8 are still
223             // broken
224             me.grid.getView().el.focus((Ext.isWebKit || Ext.isIE) ? 10 : false);
225         }
226     },
227
228     completeEdit: function() {
229         var activeEd = this.getActiveEditor();
230         if (activeEd) {
231             activeEd.completeEdit();
232         }
233     },
234
235     // internal getters/setters
236     setActiveEditor: function(ed) {
237         this.activeEditor = ed;
238     },
239
240     getActiveEditor: function() {
241         return this.activeEditor;
242     },
243
244     setActiveColumn: function(column) {
245         this.activeColumn = column;
246     },
247
248     getActiveColumn: function() {
249         return this.activeColumn;
250     },
251
252     setActiveRecord: function(record) {
253         this.activeRecord = record;
254     },
255
256     getActiveRecord: function() {
257         return this.activeRecord;
258     },
259
260     getEditor: function(record, column) {
261         var editors = this.editors,
262             editorId = column.itemId || column.id,
263             editor = editors.getByKey(editorId);
264
265         if (editor) {
266             return editor;
267         } else {
268             editor = column.getEditor(record);
269             if (!editor) {
270                 return false;
271             }
272
273             // Allow them to specify a CellEditor in the Column
274             if (!(editor instanceof Ext.grid.CellEditor)) {
275                 editor = Ext.create('Ext.grid.CellEditor', {
276                     editorId: editorId,
277                     field: editor
278                 });
279             }
280             editor.parentEl = this.grid.getEditorParent();
281             // editor.parentEl should be set here.
282             editor.on({
283                 scope: this,
284                 specialkey: this.onSpecialKey,
285                 complete: this.onEditComplete,
286                 canceledit: this.cancelEdit
287             });
288             editors.add(editor);
289             return editor;
290         }
291     },
292
293 <span id='Ext-grid.plugin.CellEditing-method-getCell'>    /**
294 </span>     * Get the cell (td) for a particular record and column.
295      * @param {Ext.data.Model} record
296      * @param {Ext.grid.column.Colunm} column
297      * @private
298      */
299     getCell: function(record, column) {
300         return this.grid.getView().getCell(record, column);
301     },
302
303     onSpecialKey: function(ed, field, e) {
304         var grid = this.grid,
305             sm;
306         if (e.getKey() === e.TAB) {
307             e.stopEvent();
308             sm = grid.getSelectionModel();
309             if (sm.onEditorTab) {
310                 sm.onEditorTab(this, e);
311             }
312         }
313     },
314
315     onEditComplete : function(ed, value, startValue) {
316         var me = this,
317             grid = me.grid,
318             sm = grid.getSelectionModel(),
319             dataIndex = me.getActiveColumn().dataIndex;
320
321         me.setActiveEditor(null);
322         me.setActiveColumn(null);
323         me.setActiveRecord(null);
324         delete sm.wasEditing;
325
326         if (!me.validateEdit()) {
327             return;
328         }
329         me.context.record.set(dataIndex, value);
330         me.fireEvent('edit', me, me.context);
331     },
332
333 <span id='Ext-grid.plugin.CellEditing-method-cancelEdit'>    /**
334 </span>     * Cancel any active editing.
335      */
336     cancelEdit: function() {
337         var me = this,
338             activeEd = me.getActiveEditor(),
339             viewEl = me.grid.getView().el;
340
341         me.setActiveEditor(null);
342         me.setActiveColumn(null);
343         me.setActiveRecord(null);
344         if (activeEd) {
345             activeEd.cancelEdit();
346             viewEl.focus();
347         }
348     },
349
350 <span id='Ext-grid.plugin.CellEditing-method-startEditByPosition'>    /**
351 </span>     * Starts editing by position (row/column)
352      * @param {Object} position A position with keys of row and column.
353      */
354     startEditByPosition: function(position) {
355         var me = this,
356             grid = me.grid,
357             sm = grid.getSelectionModel(),
358             editRecord = grid.store.getAt(position.row),
359             editColumnHeader = grid.headerCt.getHeaderAtIndex(position.column);
360
361         if (sm.selectByPosition) {
362             sm.selectByPosition(position);
363         }
364         me.startEdit(editRecord, editColumnHeader);
365     }
366 });</pre></pre></body></html>