2 * @class Ext.grid.plugin.RowEditing
3 * @extends Ext.grid.plugin.Editing
5 * The Ext.grid.plugin.RowEditing plugin injects editing at a row level for a Grid. When editing begins,
6 * a small floating dialog will be shown for the appropriate row. Each editable column will show a field
7 * for editing. There is a button to save or cancel all changes for the edit.
9 * The field that will be used for the editor is defined at the
10 * {@link Ext.grid.column.Column#field field}. The editor can be a field instance or a field configuration.
11 * If an editor is not specified for a particular column then that column won't be editable and the value of
12 * the column will be displayed.
13 * The editor may be shared for each column in the grid, or a different one may be specified for each column.
14 * An appropriate field type should be chosen to match the data structure that it will be editing. For example,
15 * to edit a date, it would be useful to specify {@link Ext.form.field.Date} as the editor.
17 * {@img Ext.grid.plugin.RowEditing/Ext.grid.plugin.RowEditing.png Ext.grid.plugin.RowEditing plugin}
20 * Ext.create('Ext.data.Store', {
21 * storeId:'simpsonsStore',
22 * fields:['name', 'email', 'phone'],
24 * {"name":"Lisa", "email":"lisa@simpsons.com", "phone":"555-111-1224"},
25 * {"name":"Bart", "email":"bart@simpsons.com", "phone":"555--222-1234"},
26 * {"name":"Homer", "email":"home@simpsons.com", "phone":"555-222-1244"},
27 * {"name":"Marge", "email":"marge@simpsons.com", "phone":"555-222-1254"}
38 * Ext.create('Ext.grid.Panel', {
40 * store: Ext.data.StoreManager.lookup('simpsonsStore'),
42 * {header: 'Name', dataIndex: 'name', field: 'textfield'},
43 * {header: 'Email', dataIndex: 'email', flex:1,
49 * {header: 'Phone', dataIndex: 'phone'}
51 * selType: 'rowmodel',
53 * Ext.create('Ext.grid.plugin.RowEditing', {
59 * renderTo: Ext.getBody()
65 Ext.define('Ext.grid.plugin.RowEditing', {
66 extend: 'Ext.grid.plugin.Editing',
67 alias: 'plugin.rowediting',
76 * @cfg {Boolean} autoCancel
77 * `true` to automatically cancel any pending changes when the row editor begins editing a new row.
78 * `false` to force the user to explicitly cancel the pending changes. Defaults to `true`.
84 * @cfg {Number} clicksToMoveEditor
85 * The number of clicks to move the row editor to a new row while it is visible and actively editing another row.
86 * This will default to the same value as {@link Ext.grid.plugin.Editing#clicksToEdit clicksToEdit}.
91 * @cfg {Boolean} errorSummary
92 * `true` to show a {@link Ext.tip.ToolTip tooltip} that summarizes all validation errors present
93 * in the row editor. Set to `false` to prevent the tooltip from showing. Defaults to `true`.
100 * Fires before row editing is triggered. The edit event object has the following properties <br />
101 * <ul style="padding:5px;padding-left:16px;">
102 * <li>grid - The grid this editor is on</li>
103 * <li>view - The grid view</li>
104 * <li>store - The grid store</li>
105 * <li>record - The record being edited</li>
106 * <li>row - The grid table row</li>
107 * <li>column - The grid {@link Ext.grid.column.Column Column} defining the column that initiated the edit</li>
108 * <li>rowIdx - The row index that is being edited</li>
109 * <li>colIdx - The column index that initiated the edit</li>
110 * <li>cancel - Set this to true to cancel the edit or return false from your handler.</li>
112 * @param {Ext.grid.plugin.Editing} editor
113 * @param {Object} e An edit event (see above for description)
117 * Fires after a row is edited. The edit event object has the following properties <br />
118 * <ul style="padding:5px;padding-left:16px;">
119 * <li>grid - The grid this editor is on</li>
120 * <li>view - The grid view</li>
121 * <li>store - The grid store</li>
122 * <li>record - The record being edited</li>
123 * <li>row - The grid table row</li>
124 * <li>column - The grid {@link Ext.grid.column.Column Column} defining the column that initiated the edit</li>
125 * <li>rowIdx - The row index that is being edited</li>
126 * <li>colIdx - The column index that initiated the edit</li>
130 grid.on('edit', onEdit, this);
133 // execute an XHR to send/commit data to the server, in callback do (if successful):
137 * @param {Ext.grid.plugin.Editing} editor
138 * @param {Object} e An edit event (see above for description)
141 * @event validateedit
142 * Fires after a cell is edited, but before the value is set in the record. Return false
143 * to cancel the change. The edit event object has the following properties <br />
144 * <ul style="padding:5px;padding-left:16px;">
145 * <li>grid - The grid this editor is on</li>
146 * <li>view - The grid view</li>
147 * <li>store - The grid store</li>
148 * <li>record - The record being edited</li>
149 * <li>row - The grid table row</li>
150 * <li>column - The grid {@link Ext.grid.column.Column Column} defining the column that initiated the edit</li>
151 * <li>rowIdx - The row index that is being edited</li>
152 * <li>colIdx - The column index that initiated the edit</li>
153 * <li>cancel - Set this to true to cancel the edit or return false from your handler.</li>
155 * Usage example showing how to remove the red triangle (dirty record indicator) from some
156 * records (not all). By observing the grid's validateedit event, it can be cancelled if
157 * the edit occurs on a targeted row (for example) and then setting the field's new value
158 * in the Record directly:
160 grid.on('validateedit', function(e) {
163 if (e.rowIdx == myTargetRow) {
165 e.record.data[e.field] = e.value;
169 * @param {Ext.grid.plugin.Editing} editor
170 * @param {Object} e An edit event (see above for description)
173 constructor: function() {
175 me.callParent(arguments);
177 if (!me.clicksToMoveEditor) {
178 me.clicksToMoveEditor = me.clicksToEdit;
181 me.autoCancel = !!me.autoCancel;
186 * AbstractComponent calls destroy on all its plugins at destroy time.
188 destroy: function() {
190 Ext.destroy(me.editor);
191 me.callParent(arguments);
195 * Start editing the specified record, using the specified Column definition to define which field is being edited.
196 * @param {Model} record The Store data record which backs the row to be edited.
197 * @param {Model} columnHeader The Column object defining the column to be edited.
200 startEdit: function(record, columnHeader) {
202 editor = me.getEditor();
204 if (me.callParent(arguments) === false) {
208 // Fire off our editor
209 if (editor.beforeEdit() !== false) {
210 editor.startEdit(me.context.record, me.context.column);
215 cancelEdit: function() {
219 me.getEditor().cancelEdit();
220 me.callParent(arguments);
225 completeEdit: function() {
228 if (me.editing && me.validateEdit()) {
230 me.fireEvent('edit', me.context);
235 validateEdit: function() {
237 return me.callParent(arguments) && me.getEditor().completeEdit();
241 getEditor: function() {
245 me.editor = me.initEditor();
251 initEditor: function() {
255 headerCt = grid.headerCt;
257 return Ext.create('Ext.grid.RowEditor', {
258 autoCancel: me.autoCancel,
259 errorSummary: me.errorSummary,
260 fields: headerCt.getGridColumns(),
263 // keep a reference..
270 initEditTriggers: function() {
274 headerCt = grid.headerCt,
275 moveEditorEvent = me.clicksToMoveEditor === 1 ? 'click' : 'dblclick';
277 me.callParent(arguments);
279 if (me.clicksToMoveEditor !== me.clicksToEdit) {
280 me.mon(view, 'cell' + moveEditorEvent, me.moveEditorByClick, me);
283 view.on('render', function() {
287 remove: me.onColumnRemove,
288 columnresize: me.onColumnResize,
289 columnhide: me.onColumnHide,
290 columnshow: me.onColumnShow,
291 columnmove: me.onColumnMove,
294 }, me, { single: true });
297 startEditByClick: function() {
299 if (!me.editing || me.clicksToMoveEditor === me.clicksToEdit) {
300 me.callParent(arguments);
304 moveEditorByClick: function() {
307 me.superclass.startEditByClick.apply(me, arguments);
312 onColumnAdd: function(ct, column) {
314 editor = me.getEditor();
316 me.initFieldAccessors(column);
317 if (editor && editor.onColumnAdd) {
318 editor.onColumnAdd(column);
323 onColumnRemove: function(ct, column) {
325 editor = me.getEditor();
327 if (editor && editor.onColumnRemove) {
328 editor.onColumnRemove(column);
330 me.removeFieldAccessors(column);
334 onColumnResize: function(ct, column, width) {
336 editor = me.getEditor();
338 if (editor && editor.onColumnResize) {
339 editor.onColumnResize(column, width);
344 onColumnHide: function(ct, column) {
346 editor = me.getEditor();
348 if (editor && editor.onColumnHide) {
349 editor.onColumnHide(column);
354 onColumnShow: function(ct, column) {
356 editor = me.getEditor();
358 if (editor && editor.onColumnShow) {
359 editor.onColumnShow(column);
364 onColumnMove: function(ct, column, fromIdx, toIdx) {
366 editor = me.getEditor();
368 if (editor && editor.onColumnMove) {
369 editor.onColumnMove(column, fromIdx, toIdx);
374 setColumnField: function(column, field) {
376 me.callParent(arguments);
377 me.getEditor().setField(column.field, column);