/** * The Cell Editing plugin utilizes an `Ext.Editor` to provide inline cell editing for * grid cells. * * ```javascript * @example({ framework: 'extjs' }) * var store = Ext.create('Ext.data.Store', { * fields: ['fname', 'lname', 'talent'], * data: [ * { 'fname': 'Barry', 'lname': 'Allen', 'talent': 'Speedster'}, * { 'fname': 'Oliver', 'lname': 'Queen', 'talent': 'Archery'}, * { 'fname': 'Kara', 'lname': 'Zor-El', 'talent': 'All'}, * { 'fname': 'Helena', 'lname': 'Bertinelli', 'talent': 'Weapons Expert'}, * { 'fname': 'Hal', 'lname': 'Jordan', 'talent': 'Willpower' }, * ] * }); * * Ext.create('Ext.grid.Grid', { * title: 'DC Personnel', * * store: store, * plugins: { * cellediting: true * }, * columns: [ * { text: 'First Name', dataIndex: 'fname', flex: 1, editable: true }, * { text: 'Last Name', dataIndex: 'lname', flex: 1 }, * { text: 'Talent', dataIndex: 'talent', flex: 1 } * ], * fullscreen: true * }); * ``` * ```html * @example({framework: 'ext-web-components', packages:['ext-web-components'], tab: 1 }) * <ext-container width="100%" height="100%"> * <ext-grid * shadow="true" * height="275" * plugins='["cellediting"]' * onready="editablegrid.onGridReady" * > * <ext-column text="First Name" dataIndex="fname" flex="1" editable="true"></ext-column> * <ext-column text="Last Name" dataIndex="lname" flex="1" editable="true"></ext-column> * <ext-column text="Talent" dataIndex="talent" flex="1" editable="true"></ext-column> * </ext-grid> * </ext-container> * ``` * ```javascript * @example({framework: 'ext-web-components', tab: 2, packages: ['ext-web-components']}) * import '@sencha/ext-web-components/dist/ext-container.component'; * import '@sencha/ext-web-components/dist/ext-grid.component'; * import '@sencha/ext-web-components/dist/ext-column.component'; * * Ext.require('Ext.grid.plugin.Editable'); * * export default class EditableGridComponent { * constructor() { * this.store = new Ext.data.Store({ * data: [ * { 'fname': 'Barry', 'lname': 'Allen', 'talent': 'Speedster'}, * { 'fname': 'Oliver', 'lname': 'Queen', 'talent': 'Archery'}, * { 'fname': 'Kara', 'lname': 'Zor-El', 'talent': 'All'}, * { 'fname': 'Helena', 'lname': 'Bertinelli', 'talent': 'Weapons Expert'}, * { 'fname': 'Hal', 'lname': 'Jordan', 'talent': 'Willpower' } * ] * }); * } * * onGridReady(event) { * this.editableGridCmp = event.detail.cmp; * this.editableGridCmp.setStore(this.store); * } * } * window.editablegrid = new EditableGridComponent(); * ``` * ```javascript * @example({framework: 'ext-react', packages:['ext-react']}) * import React, { Component } from 'react' * import { ExtGrid, ExtColumn, ExtSelectField } from '@sencha/ext-react'; * * Ext.require('Ext.grid.plugin.CellEditing'); * * export default class MyExample extends Component { * * store = new Ext.data.Store({ * data: [ * { 'fname': 'Barry', 'lname': 'Allen', 'talent': 'Speedster'}, * { 'fname': 'Oliver', 'lname': 'Queen', 'talent': 'Archery'}, * { 'fname': 'Kara', 'lname': 'Zor-El', 'talent': 'All'}, * { 'fname': 'Helena', 'lname': 'Bertinelli', 'talent': 'Weapons Expert'}, * { 'fname': 'Hal', 'lname': 'Jordan', 'talent': 'Willpower' } * ] * }); * * render() { * return ( * <ExtGrid * height="275" * store={this.store} * plugins={['cellediting']} * > * <ExtColumn * text="First Name" * dataIndex="fname" * flex={1} * editable * /> * <ExtColumn * text="Last Name" * dataIndex="lname" * flex={1} * editable * /> * <ExtColumn * text="Talent" * dataIndex="talent" * flex={1} * editable * > * <ExtSelectField * options={[ * { text: 'All', value: 'All' }, * { text: 'Archery', value: 'Archery' }, * { text: 'Speedster', value: 'Speedster' }, * { text: 'Weapons', value: 'Weapons' }, * { text: 'Willpower', value: 'Willpower' } * ]} * /> * </ExtColumn> * </ExtGrid> * ) * } * } * ``` * ```javascript * @example({framework: 'ext-angular', packages:['ext-angular']}) * import { Component } from '@angular/core' * declare var Ext: any; * * @Component({ * selector: 'app-root-1', * styles: [` * `], * template: ` * <ExtContainer> * <ExtGrid * [height]="'275px'" * [store]="this.store" * [plugins]="['cellediting']" * > * <ExtColumn * text="First Name" * dataIndex="fname" * flex="1" * editable="true" * ></ExtColumn> * <ExtColumn * text="Last Name" * dataIndex="lname" * flex="1" * editable="true" * ></ExtColumn> * <ExtColumn * text="Talent" * dataIndex="talent" * flex="1" * editable="true" * > * <ExtSelectField * [options]="[ * { text: 'All', value: 'All' }, * { text: 'Archery', value: 'Archery' }, * { text: 'Speedster', value: 'Speedster' }, * { text: 'Weapons', value: 'Weapons' }, * { text: 'Willpower', value: 'Willpower' } * ]" * ></ExtSelectField> * </ExtColumn> * </ExtGrid> * </ExtContainer> * ` * }) * export class AppComponent { * store = new Ext.data.Store({ * data: [ * { 'fname': 'Barry', 'lname': 'Allen', 'talent': 'Speedster'}, * { 'fname': 'Oliver', 'lname': 'Queen', 'talent': 'Archery'}, * { 'fname': 'Kara', 'lname': 'Zor-El', 'talent': 'All'}, * { 'fname': 'Helena', 'lname': 'Bertinelli', 'talent': 'Weapons Expert'}, * { 'fname': 'Hal', 'lname': 'Jordan', 'talent': 'Willpower' } * ] * }); * * } * ``` * * @since 6.5.0 */Ext.define('Ext.grid.plugin.CellEditing', { extend: 'Ext.plugin.Abstract', alias: ['plugin.gridcellediting', 'plugin.cellediting'], requires: [ 'Ext.grid.CellEditor', 'Ext.grid.Location' ], config: { /** * @private */ grid: null, /** * @cfg {String} triggerEvent * An optional pointer event to trigger cell editing. * * By default, cell editing begins when actionable mode is entered by pressing * `ENTER` or `F2` when focused on the cell. */ triggerEvent: 'doubletap', /** * @cfg {Boolean} [selectOnEdit=false] * Configure as `true` to have the cell editor *select* the cell it is editing (If * cell selection enabled), or the record it is editing (if row selection enabled) */ selectOnEdit: null }, init: function(grid) { this.setGrid(grid); grid.setTouchAction({ doubleTapZoom: false }); grid.$cellEditing = true; }, getEditor: function(location) { var column = location.column, fieldName = column.getDataIndex(), record = location.record, editable = column.getEditable(), editor, field; if (!(editor = editable !== false && column.getEditor(location.record)) && editable) { editor = Ext.create(column.getDefaultEditor()); } if (editor) { if (!editor.isCellEditor) { // during the construction of the celleditor // we need to pass the plugin so it can find // the owner grid to relay it's own events editor = Ext.create({ xtype: 'celleditor', field: editor, plugin: this }); } column.setEditor(editor); editor.editingPlugin = this; field = editor.getField(); field.addUi('celleditor'); // Enforce the Model's validation rules field.setValidationField(record.getField(fieldName), record); } return editor; }, getActiveEditor: function() { return this.activeEditor; }, updateGrid: function(grid, oldGrid) { if (oldGrid) { oldGrid.unregisterActionable(this); } if (grid) { grid.registerActionable(this); } }, /** * @protected * Part of the grid Actionable interface. * * Callback called by the NavigationModel on entry into actionable mode at the specified * position. * @param {Ext.grid.Location} location The position at which to enter actionable mode. * @return {Ext.grid.Location} The location where actionable mode was successfully started. */ activateCell: function(location) { var me = this, activeEditor = me.activeEditor, previousEditor = me.$previousEditor, editor, selModel, result; //<debug> if (!location) { Ext.raise('A grid Location must be passed into CellEditing#activateCell'); } //</debug> // Do not restart editor on the same cell. This may happen when an actionable's // triggerEvent happens in a cell editor, and the event bubbles up to the // NavigationModel which will try to activate the owning cell. // In this case, we return the location to indicate that it's still a successful edit. if (activeEditor && activeEditor.editing && activeEditor.$activeLocation.cell === location.cell) { return activeEditor.$activeLocation; } else { editor = me.getEditor(location); if (editor) { if (previousEditor) { if (previousEditor.isCancelling) { previousEditor.cancelEdit(); } else { previousEditor.completeEdit(); } } result = editor.startEdit(location); if (editor.editing) { // Select the edit location if possible if we have been configured to do so. if (me.getSelectOnEdit()) { selModel = me.getGrid().getSelectable(); if (selModel.getCells()) { selModel.selectCells(location, location); } else if (selModel.getRows()) { selModel.select(location.record); } } me.$previousEditor = editor; return result; } else { editor.onEditComplete(false, true); } } } }, // for compatibility startEdit: function(record, column) { this.activateCell(new Ext.grid.Location(this.getGrid(), { record: record, column: column })); }, destroy: function() { var grid = this.getGrid(); if (grid) { grid.$cellEditing = false; } this.$previousEditor = null; this.callParent(); }});