Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / RowEditing.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-grid-plugin-RowEditing'>/**
19 </span> * The Ext.grid.plugin.RowEditing plugin injects editing at a row level for a Grid. When editing begins,
20  * a small floating dialog will be shown for the appropriate row. Each editable column will show a field
21  * for editing. There is a button to save or cancel all changes for the edit.
22  *
23  * The field that will be used for the editor is defined at the
24  * {@link Ext.grid.column.Column#editor editor}. The editor can be a field instance or a field configuration.
25  * If an editor is not specified for a particular column then that column won't be editable and the value of
26  * the column will be displayed.
27  *
28  * The editor may be shared for each column in the grid, or a different one may be specified for each column.
29  * An appropriate field type should be chosen to match the data structure that it will be editing. For example,
30  * to edit a date, it would be useful to specify {@link Ext.form.field.Date} as the editor.
31  *
32  *     @example
33  *     Ext.create('Ext.data.Store', {
34  *         storeId:'simpsonsStore',
35  *         fields:['name', 'email', 'phone'],
36  *         data: [
37  *             {&quot;name&quot;:&quot;Lisa&quot;, &quot;email&quot;:&quot;lisa@simpsons.com&quot;, &quot;phone&quot;:&quot;555-111-1224&quot;},
38  *             {&quot;name&quot;:&quot;Bart&quot;, &quot;email&quot;:&quot;bart@simpsons.com&quot;, &quot;phone&quot;:&quot;555--222-1234&quot;},
39  *             {&quot;name&quot;:&quot;Homer&quot;, &quot;email&quot;:&quot;home@simpsons.com&quot;, &quot;phone&quot;:&quot;555-222-1244&quot;},
40  *             {&quot;name&quot;:&quot;Marge&quot;, &quot;email&quot;:&quot;marge@simpsons.com&quot;, &quot;phone&quot;:&quot;555-222-1254&quot;}
41  *         ]
42  *     });
43  *
44  *     Ext.create('Ext.grid.Panel', {
45  *         title: 'Simpsons',
46  *         store: Ext.data.StoreManager.lookup('simpsonsStore'),
47  *         columns: [
48  *             {header: 'Name',  dataIndex: 'name', editor: 'textfield'},
49  *             {header: 'Email', dataIndex: 'email', flex:1,
50  *                 editor: {
51  *                     xtype: 'textfield',
52  *                     allowBlank: false
53  *                 }
54  *             },
55  *             {header: 'Phone', dataIndex: 'phone'}
56  *         ],
57  *         selType: 'rowmodel',
58  *         plugins: [
59  *             Ext.create('Ext.grid.plugin.RowEditing', {
60  *                 clicksToEdit: 1
61  *             })
62  *         ],
63  *         height: 200,
64  *         width: 400,
65  *         renderTo: Ext.getBody()
66  *     });
67  */
68 Ext.define('Ext.grid.plugin.RowEditing', {
69     extend: 'Ext.grid.plugin.Editing',
70     alias: 'plugin.rowediting',
71
72     requires: [
73         'Ext.grid.RowEditor'
74     ],
75
76     editStyle: 'row',
77
78 <span id='Ext-grid-plugin-RowEditing-cfg-autoCancel'>    /**
79 </span>     * @cfg {Boolean} autoCancel
80      * True to automatically cancel any pending changes when the row editor begins editing a new row.
81      * False to force the user to explicitly cancel the pending changes. Defaults to true.
82      */
83     autoCancel: true,
84
85 <span id='Ext-grid-plugin-RowEditing-cfg-clicksToMoveEditor'>    /**
86 </span>     * @cfg {Number} clicksToMoveEditor
87      * The number of clicks to move the row editor to a new row while it is visible and actively editing another row.
88      * This will default to the same value as {@link Ext.grid.plugin.Editing#clicksToEdit clicksToEdit}.
89      */
90
91 <span id='Ext-grid-plugin-RowEditing-cfg-errorSummary'>    /**
92 </span>     * @cfg {Boolean} errorSummary
93      * True to show a {@link Ext.tip.ToolTip tooltip} that summarizes all validation errors present
94      * in the row editor. Set to false to prevent the tooltip from showing. Defaults to true.
95      */
96     errorSummary: true,
97
98 <span id='Ext-grid-plugin-RowEditing-event-beforeedit'>    /**
99 </span>     * @event beforeedit
100      * Fires before row editing is triggered.
101      *
102      * @param {Ext.grid.plugin.Editing} editor
103      * @param {Object} e An edit event with the following properties:
104      *
105      * - grid - The grid this editor is on
106      * - view - The grid view
107      * - store - The grid store
108      * - record - The record being edited
109      * - row - The grid table row
110      * - column - The grid {@link Ext.grid.column.Column Column} defining the column that initiated the edit
111      * - rowIdx - The row index that is being edited
112      * - colIdx - The column index that initiated the edit
113      * - cancel - Set this to true to cancel the edit or return false from your handler.
114      */
115     
116 <span id='Ext-grid-plugin-RowEditing-event-canceledit'>    /**
117 </span>     * @event canceledit
118      * Fires when the user has started editing a row but then cancelled the edit
119      * @param {Object} grid The grid
120      */
121     
122 <span id='Ext-grid-plugin-RowEditing-event-edit'>    /**
123 </span>     * @event edit
124      * Fires after a row is edited. Usage example:
125      *
126      *     grid.on('edit', function(editor, e) {
127      *         // commit the changes right after editing finished
128      *         e.record.commit();
129      *     };
130      *
131      * @param {Ext.grid.plugin.Editing} editor
132      * @param {Object} e An edit event with the following properties:
133      *
134      * - grid - The grid this editor is on
135      * - view - The grid view
136      * - store - The grid store
137      * - record - The record being edited
138      * - row - The grid table row
139      * - column - The grid {@link Ext.grid.column.Column Column} defining the column that initiated the edit
140      * - rowIdx - The row index that is being edited
141      * - colIdx - The column index that initiated the edit
142      */
143 <span id='Ext-grid-plugin-RowEditing-event-validateedit'>    /**
144 </span>     * @event validateedit
145      * Fires after a cell is edited, but before the value is set in the record. Return false to cancel the change. The
146      * edit event object has the following properties
147      *
148      * Usage example showing how to remove the red triangle (dirty record indicator) from some records (not all). By
149      * observing the grid's validateedit event, it can be cancelled if the edit occurs on a targeted row (for example)
150      * and then setting the field's new value in the Record directly:
151      *
152      *     grid.on('validateedit', function(editor, e) {
153      *       var myTargetRow = 6;
154      *
155      *       if (e.rowIdx == myTargetRow) {
156      *         e.cancel = true;
157      *         e.record.data[e.field] = e.value;
158      *       }
159      *     });
160      *
161      * @param {Ext.grid.plugin.Editing} editor
162      * @param {Object} e An edit event with the following properties:
163      *
164      * - grid - The grid this editor is on
165      * - view - The grid view
166      * - store - The grid store
167      * - record - The record being edited
168      * - row - The grid table row
169      * - column - The grid {@link Ext.grid.column.Column Column} defining the column that initiated the edit
170      * - rowIdx - The row index that is being edited
171      * - colIdx - The column index that initiated the edit
172      * - cancel - Set this to true to cancel the edit or return false from your handler.
173      */
174
175     constructor: function() {
176         var me = this;
177         me.callParent(arguments);
178
179         if (!me.clicksToMoveEditor) {
180             me.clicksToMoveEditor = me.clicksToEdit;
181         }
182
183         me.autoCancel = !!me.autoCancel;
184     },
185
186 <span id='Ext-grid-plugin-RowEditing-method-destroy'>    /**
187 </span>     * @private
188      * AbstractComponent calls destroy on all its plugins at destroy time.
189      */
190     destroy: function() {
191         var me = this;
192         Ext.destroy(me.editor);
193         me.callParent(arguments);
194     },
195
196 <span id='Ext-grid-plugin-RowEditing-method-startEdit'>    /**
197 </span>     * Starts editing the specified record, using the specified Column definition to define which field is being edited.
198      * @param {Ext.data.Model} record The Store data record which backs the row to be edited.
199      * @param {Ext.data.Model} columnHeader The Column object defining the column to be edited. @override
200      */
201     startEdit: function(record, columnHeader) {
202         var me = this,
203             editor = me.getEditor();
204
205         if (me.callParent(arguments) === false) {
206             return false;
207         }
208
209         // Fire off our editor
210         if (editor.beforeEdit() !== false) {
211             editor.startEdit(me.context.record, me.context.column);
212         }
213     },
214
215     // private
216     cancelEdit: function() {
217         var me = this;
218
219         if (me.editing) {
220             me.getEditor().cancelEdit();
221             me.callParent(arguments);
222             
223             me.fireEvent('canceledit', me.context);
224         }
225     },
226
227     // private
228     completeEdit: function() {
229         var me = this;
230
231         if (me.editing &amp;&amp; me.validateEdit()) {
232             me.editing = false;
233             me.fireEvent('edit', me.context);
234         }
235     },
236
237     // private
238     validateEdit: function() {
239         var me             = this,
240             editor         = me.editor,
241             context        = me.context,
242             record         = context.record,
243             newValues      = {},
244             originalValues = {},
245             name;
246
247         editor.items.each(function(item) {
248             name = item.name;
249
250             newValues[name]      = item.getValue();
251             originalValues[name] = record.get(name);
252         });
253
254         Ext.apply(context, {
255             newValues      : newValues,
256             originalValues : originalValues
257         });
258
259         return me.callParent(arguments) &amp;&amp; me.getEditor().completeEdit();
260     },
261
262     // private
263     getEditor: function() {
264         var me = this;
265
266         if (!me.editor) {
267             me.editor = me.initEditor();
268         }
269         return me.editor;
270     },
271
272     // private
273     initEditor: function() {
274         var me = this,
275             grid = me.grid,
276             view = me.view,
277             headerCt = grid.headerCt;
278
279         return Ext.create('Ext.grid.RowEditor', {
280             autoCancel: me.autoCancel,
281             errorSummary: me.errorSummary,
282             fields: headerCt.getGridColumns(),
283             hidden: true,
284
285             // keep a reference..
286             editingPlugin: me,
287             renderTo: view.el
288         });
289     },
290
291     // private
292     initEditTriggers: function() {
293         var me = this,
294             grid = me.grid,
295             view = me.view,
296             headerCt = grid.headerCt,
297             moveEditorEvent = me.clicksToMoveEditor === 1 ? 'click' : 'dblclick';
298
299         me.callParent(arguments);
300
301         if (me.clicksToMoveEditor !== me.clicksToEdit) {
302             me.mon(view, 'cell' + moveEditorEvent, me.moveEditorByClick, me);
303         }
304
305         view.on('render', function() {
306             // Column events
307             me.mon(headerCt, {
308                 add: me.onColumnAdd,
309                 remove: me.onColumnRemove,
310                 columnresize: me.onColumnResize,
311                 columnhide: me.onColumnHide,
312                 columnshow: me.onColumnShow,
313                 columnmove: me.onColumnMove,
314                 scope: me
315             });
316         }, me, { single: true });
317     },
318
319     startEditByClick: function() {
320         var me = this;
321         if (!me.editing || me.clicksToMoveEditor === me.clicksToEdit) {
322             me.callParent(arguments);
323         }
324     },
325
326     moveEditorByClick: function() {
327         var me = this;
328         if (me.editing) {
329             me.superclass.startEditByClick.apply(me, arguments);
330         }
331     },
332
333     // private
334     onColumnAdd: function(ct, column) {
335         if (column.isHeader) {
336             var me = this,
337                 editor;
338
339             me.initFieldAccessors(column);
340             editor = me.getEditor();
341
342             if (editor &amp;&amp; editor.onColumnAdd) {
343                 editor.onColumnAdd(column);
344             }
345         }
346     },
347
348     // private
349     onColumnRemove: function(ct, column) {
350         if (column.isHeader) {
351             var me = this,
352                 editor = me.getEditor();
353
354             if (editor &amp;&amp; editor.onColumnRemove) {
355                 editor.onColumnRemove(column);
356             }
357             me.removeFieldAccessors(column);
358         }
359     },
360
361     // private
362     onColumnResize: function(ct, column, width) {
363         if (column.isHeader) {
364             var me = this,
365                 editor = me.getEditor();
366
367             if (editor &amp;&amp; editor.onColumnResize) {
368                 editor.onColumnResize(column, width);
369             }
370         }
371     },
372
373     // private
374     onColumnHide: function(ct, column) {
375         // no isHeader check here since its already a columnhide event.
376         var me = this,
377             editor = me.getEditor();
378
379         if (editor &amp;&amp; editor.onColumnHide) {
380             editor.onColumnHide(column);
381         }
382     },
383
384     // private
385     onColumnShow: function(ct, column) {
386         // no isHeader check here since its already a columnshow event.
387         var me = this,
388             editor = me.getEditor();
389
390         if (editor &amp;&amp; editor.onColumnShow) {
391             editor.onColumnShow(column);
392         }
393     },
394
395     // private
396     onColumnMove: function(ct, column, fromIdx, toIdx) {
397         // no isHeader check here since its already a columnmove event.
398         var me = this,
399             editor = me.getEditor();
400
401         if (editor &amp;&amp; editor.onColumnMove) {
402             editor.onColumnMove(column, fromIdx, toIdx);
403         }
404     },
405
406     // private
407     setColumnField: function(column, field) {
408         var me = this;
409         me.callParent(arguments);
410         me.getEditor().setField(column.field, column);
411     }
412 });
413 </pre>
414 </body>
415 </html>