CellEdit

Adding this feature to the grid and other Bryntum products which are based on the Grid (i.e. Scheduler, SchedulerPro, and Gantt) enables cell editing. Any subclass of Field can be used as editor for the Column. The most popular are:

Usage instructions:

Start editing

  • Double click on a cell
  • Press [ENTER] or [F2] with a cell selected (see Keyboard shortcuts below)
  • It is also possible to change double click to single click to start editing, using the triggerEvent config
new Grid({
   features : {
       cellEdit : {
           triggerEvent : 'cellclick'
       }
   }
});

Instant update

If instantUpdate on the column is set to true, record will be updated instantly as value in the editor is changed. In combination with autoCommit it could result in excessive requests to the backend. By default instantUpdate is false, but it is enabled for some special columns, such as Duration column in Scheduler Pro and all date columns in Gantt.

Keyboard shortcuts

While not editing

Keys Action Action description
Enter startEditing Starts editing currently focused cell
F2 startEditing Starts editing currently focused cell

While editing

Keys Action Weight Action description
Enter finishAndEditNextRow Finish editing and start editing the same cell in next row
Shift+Enter finishAndEditPrevRow Finish editing and start editing the same cell in previous row
F2 finishEditing Finish editing
Ctrl+Enter finishAllSelected If multiEdit is active, this applies new value on all selected rows/cells
Ctrl+Enter finishEditing Finish editing
Escape cancelEditing By default, first reverts the value back to its original value, next press cancels editing
Tab finishAndEditNextCell 100 Finish editing and start editing the next cell with a configured editor
Shift+Tab finishAndEditPrevCell 100 Finish editing and start editing the previous cell with a configured editor
Please note that Ctrl is the equivalent to Command and Alt is the equivalent to Option for Mac users

When using the Tab key to navigate between cells, the editor will skip over cells which contain naturally focusable elements, such as buttons or input fields. To have these included in the tabbing, configure the tabToFocusables setting as true.

For more information on how to customize keyboard shortcuts, please see our guide.

Editor configuration

Columns specify editor in their configuration. Editor can also by set by using a column type. Columns may also contain these three configurations which affect how their cells are edited:

Preventing editing of certain cells

You can prevent editing on a column by setting editor to false:

new Grid({
   columns : [
      {
         type   : 'number',
         text   : 'Age',
         field  : 'age',
         editor : false
      }
   ]
});

To prevent editing in a specific cell, listen to the beforeCellEditStart and return false:

grid.on('beforeCellEditStart', ({ editorContext }) => {
    return editorContext.column.field !== 'id';
});

Choosing field on the fly

To use an alternative input field to edit a cell, listen to the beforeCellEditStart and set the editor property of the context to the input field you want to use:

grid.on('beforeCellEditStart', ({ editorContext }) => {
    return editorContext.editor = myDateField;
});

Loading remote data into a combo box cell editor

If you need to prepare or modify the data shown by the cell editor, e.g. load remote data into the store used by a combo, listen to the startCellEdit event:

const employeeStore = new AjaxStore({ readUrl : '/cities' }); // A server endpoint returning data like:
                                                              // [{ id : 123, name : 'Bob Mc Bob' }, { id : 345, name : 'Lind Mc Foo' }]

new Grid({
    // Example data including a city field which is an id used to look up entries in the cityStore above
    data : [
        { id : 1, name : 'Task 1', employeeId : 123 },
        { id : 2, name : 'Task 2', employeeId : 345 }
    ],
    columns : [
      {
         text   : 'Task',
         field  : 'name'
      },
      {
         text   : 'Assigned to',
         field  : 'employeeId',
         editor : {
              type : 'combo',
              store : employeeStore,
              // specify valueField'/'displayField' to match the data format in the employeeStore store
              valueField : 'id',
              displayField : 'name'
          },
          renderer : ({ value }) {
               // Use a renderer to show the employee name, which we find by querying employeeStore by the id of the grid record
               return employeeStore.getById(value)?.name;
          }
      }
   ],
   listeners : {
       // When editing, you might want to fetch data for the combo store from a remote resource
       startCellEdit({ editorContext }) {
           const { record, editor, column } = editorContext;
           if (column.field === 'employeeId') {
               // Load possible employees to assign to this particular task
               editor.inputField.store.load({ task : record.id });
           }
      }
   }
});

Editing on touch devices

On touch devices, a single tap navigates and tapping an already selected cell after a short delay starts the editing.

This feature is enabled by default.

Validation

To validate the cell editing process you can use the finalizeCellEdit config. Please refer to its documentation for details.

The following example requires a name of a minimum of 5 characters and a score of less than 1,000 for Paris city.

Cell editing
//<code-header>
fiddle.title = 'Cell editing';
//</code-header>
// grid with cell editing
const grid = new Grid({
    appendTo : targetElement,

    // makes grid as high as it needs to be to fit rows
    autoHeight : true,

    features : {
        // cellEditing is enabled by default, so this is not necessary
        cellEdit : true
    },

    data : DataGenerator.generateData(5),

    columns : [
        // basic columns has a TextField as editor by default
        {
            field            : 'name',
            text             : 'Name',
            flex             : 1,
            // Invoked on final edit of input field, typically after pressing enter or blurring the field.
            finalizeCellEdit : ({ value }) => {
                // returning true will accept the new value otherwise it shows the return statement as error message
                return value.trim().length < 5 ? 'Name should be at least 5 characters' : true;
            }
        },
        // a custom editor can be specified
        {
            field  : 'city',
            text   : 'City',
            flex   : 1,
            editor : {
                type  : 'combo',
                items : ['Stockholm', 'New York', 'Montreal']
            }
        },
        // column types may specify an editor
        // NumberColumn for example uses a NumberField
        {
            type             : 'number',
            field            : 'score',
            text             : 'Score',
            flex             : 1,
            finalizeCellEdit : ({ value, record }) => {

                // record contains sibling column's data
                const { city } = record;

                // Perform validation based on a sibling column
                if (city == 'Paris' && value > 999) {
                    return "Score can't be higher than 999 for Paris";
                }
                return true;
            }
        },
        // specify editor: false to make a column "readonly"
        { type : 'number', field : 'age', text : 'Age (readonly)', flex : 1, editor : false }
    ]
});

You can use the value parameter to add validation to accept a value of minimum 5 characters:

// Column
{
 field: 'name',
 text: 'Name',
 flex: 1,
 finalizeCellEdit: ({ value }) => {
     // Implement your validation logic here
     if (value.trim().length < 5) {
         return "Name should be at least 5 characters";
     }

     // Return true to allow the edit to be finalized
     return true;
 }
}

Along with the value, it also contains other parameters, such as data.record property, which provides a way to access and validate other columns based on their values.

In the following example, validation is performed based on the 'Score' column's value and the value of its sibling column ('City'):

      {
          type             : 'number',
          field            : 'score',
          text             : 'Score',
          flex             : 1,
          finalizeCellEdit : ({ value, record }) => {

              // record contains sibling column's data e.g. city
              const { city } = record;

              // Perform validation based on a sibling column
              if (city == 'Paris' && value > 999) {
                  return "Score can't be higher than 999 for Paris";
              }
              return true;
          }
      },

Configs

22

Common

disabledInstancePlugin
listenersEvents

Other

addNewAtEnd: Boolean | Object

Set to true to have TAB key on the last cell (and ENTER anywhere in the last row) in the data set create a new record and begin editing it at its first editable cell.

If a customized keyMap is used, this setting will affect the customized keys instead of ENTER and TAB.

If this is configured as an object, it is used as the default data value set for each new record.

Set to true to add record to the parent of the last record, when configured with addNewAtEnd. Only applicable when using a tree view and store.

By default, it adds records to the root.

autoSelect: Boolean= true

Set to true to select the field text when editing starts

blurAction: complete | cancel= complete

What action should be taken when focus moves leaves the cell editor, for example when clicking outside. May be 'complete' or 'cancel'.

editNextOnEnterPress: Boolean= true

Set to false to not start editing next record when user presses enter inside a cell editor (or previous record if SHIFT key is pressed). This is set to false when autoEdit is true. Please note that these key combinations could be different if a customized keyMap is used.

keyMap: Object<String, KeyMapConfig>

See Keyboard shortcuts for details

multiEdit: Boolean= true

If set to true (which is default) this will make it possible to edit current column in multiple rows simultaneously.

This is achieved by:

  1. Select multiple rows or row's cells
  2. Start editing simultaneously as selecting the last row or cell
  3. When finished editing, press Ctrl+Enter to apply the new value to all selected rows.

If a customized keyMap is used, the Ctrl+Enter combination could map to something else.

scrollAction: complete | cancel | nullAlso a property

What action should be taken when the editor is scrolled out of view, for example when using a mousewheel to scroll the grid. May be 'complete' or 'cancel' or null.

By default, when cell editing is active, the TAB key will move focus to edit the next cell with a configured editor.

This will skip over cells which contain naturally focusable elements, such as buttons or input fields.

To have these included in the tabbing, configure this as true.

autoEditGridEditBase
ignoreCSSSelectorGridEditBase
triggerEventGridEditBase

Misc

clientInstancePlugin
localeClassLocalizable
localizableLocalizable

Properties

23

Common

disabledInstancePlugin

Class hierarchy

isCellEdit: Boolean= truereadonly
Identifies an object as an instance of CellEdit class, or subclass thereof.
isCellEdit: Boolean= truereadonlystatic
Identifies an object as an instance of CellEdit class, or subclass thereof.
isDelayableDelayable
isEventsEvents
isGridEditBaseGridEditBase
isInstancePluginInstancePlugin
isLocalizableLocalizable

Other

Set to true to add record to the parent of the last record, when configured with addNewAtEnd. Only applicable when using a tree view and store.

By default, it adds records to the root.

scrollAction: complete | cancel | nullAlso a config

What action should be taken when the editor is scrolled out of view, for example when using a mousewheel to scroll the grid. May be 'complete' or 'cancel' or null.

By default, when cell editing is active, the TAB key will move focus to edit the next cell with a configured editor.

This will skip over cells which contain naturally focusable elements, such as buttons or input fields.

To have these included in the tabbing, configure this as true.

activeRecordGridEditBase
autoEditGridEditBase
isEditingGridEditBase

Lifecycle

configBase

Misc

clientInstancePlugin
localeHelperLocalizable
localeManagerLocalizable

Functions

33

Editing

Cancel editing, hides the editor. This function is exposed on Grid and can thus be called as grid.cancelEditing(...)

ParameterTypeDescription
silentBoolean

Pass true to prevent method from firing event

Returns: Boolean -

false if the edit could not be canceled due to the editor's beforeCancel event being prevented.

Finish editing, update the underlying record and hide the editor. This function is exposed on Grid and can thus be called as grid.finishEditing(...)

Returns: Promise -

Resolved promise returns false if the edit could not be finished due to the value being invalid or the Editor's complete event was vetoed.

Start editing specified cell. If no cellContext is given it starts with the first cell of the first visible row. This function is exposed on Grid and can thus be called as grid.startEditing(...)

ParameterTypeDescription
cellContextGridLocationConfig

Cell specified in format { id: 'x', columnId/column/field: 'xxx' }. See getCell for details.

Returns: Promise -

Resolved promise returnstrue if editing has been started, false if an beforeStart listener has vetoed the edit.

Other

Displays an OK / Cancel confirmation dialog box owned by the current Editor. This is intended to be used by finalizeCellEdit implementations. The returned promise resolves passing true if the "OK" button is pressed, and false if the "Cancel" button is pressed. Typing ESC rejects.

ParameterTypeDescription
optionsObject

An options object for what to show.

options.titleString

The title to show in the dialog header.

options.messageString

The message to show in the dialog body.

options.cancelButtonString | Object

A text or a config object to apply to the Cancel button.

options.okButtonString | Object

A text or config object to apply to the OK button.

Returns: Boolean
createOnFrameDelayable
LstaticLocalizable
onEvents
relayAllEvents
triggerEvents
unEvents

Configuration

applyDefaultsstaticBase

Events

Lifecycle

destroystaticBase

Misc

doDisableInstancePlugin
initClassstaticBase
isOfTypeNamestaticBase
mixinstaticBase
optionalLstaticLocalizable

Events

13

Fires on the owning Grid before the cell editing is canceled, return false to prevent cancellation.

// Adding a listener using the "on" method
cellEdit.on('beforeCancelCellEdit', ({ source, editorContext }) => {

});
ParameterTypeDescription
sourceGrid

Owner grid

editorContextGridLocation

Editing context

Fires on the owning Grid before editing starts, return false to prevent editing

// Adding a listener using the "on" method
cellEdit.on('beforeCellEditStart', ({ source, editorContext }) => {

});
ParameterTypeDescription
sourceGrid

Owner grid

editorContextCellEditorContext

Editing context

Fires on the owning Grid before deleting a range of selected cell values by pressing Backspace or Del buttons while autoEdit is set to true. Return false to prevent editing.

// Adding a listener using the "on" method
cellEdit.on('beforeCellRangeDelete', ({ source, gridSelection }) => {

});
ParameterTypeDescription
sourceGrid

Owner grid

gridSelection(GridLocation|Model)[]

An array of cell selectors or records that will have their values deleted (the records themselves will not get deleted, only visible column values).

Fires for each selected record on the owning Grid before editing a range of selected cell values

// Adding a listener using the "on" method
cellEdit.on('beforeCellRangeEdit', ({ record, field, value }) => {

});
ParameterTypeDescription
recordModel

Current selected record from the range

fieldString

The field being changed

value*

The value being set

Fires on the owning Grid before the cell editing is finished, return false to signal that the value is invalid and editing should not be finalized.

// Adding a listener using the "on" method
cellEdit.on('beforeFinishCellEdit', ({ grid, editorContext }) => {

});
ParameterTypeDescription
gridGrid

Target grid

editorContextCellEditorContext

Editing context

Fires on the owning Grid when editing is cancelled

// Adding a listener using the "on" method
cellEdit.on('cancelCellEdit', ({ source, editorContext, event }) => {

});
ParameterTypeDescription
sourceGrid

Owner grid

editorContextGridLocation

Editing context

eventEvent

Included if the cancellation was triggered by a DOM event

Fires on the owning Grid when cell editing is finished

// Adding a listener using the "on" method
cellEdit.on('finishCellEdit', ({ grid, editorContext }) => {

});
ParameterTypeDescription
gridGrid

Target grid

editorContextCellEditorContext

Editing context

Fires on the owning Grid when editing starts

// Adding a listener using the "on" method
cellEdit.on('startCellEdit', ({ source, editorContext }) => {

});
ParameterTypeDescription
sourceGrid

Owner grid

editorContextCellEditorContext

Editing context

catchAllEvents
destroyEvents
disableInstancePlugin
enableInstancePlugin

Event handlers

13

Called on the owning Grid before the cell editing is canceled, return false to prevent cancellation.

new CellEdit({
    onBeforeCancelCellEdit({ source, editorContext }) {

    }
});
ParameterTypeDescription
sourceGrid

Owner grid

editorContextGridLocation

Editing context

Called on the owning Grid before editing starts, return false to prevent editing

new CellEdit({
    onBeforeCellEditStart({ source, editorContext }) {

    }
});
ParameterTypeDescription
sourceGrid

Owner grid

editorContextCellEditorContext

Editing context

Called on the owning Grid before deleting a range of selected cell values by pressing Backspace or Del buttons while autoEdit is set to true. Return false to prevent editing.

new CellEdit({
    onBeforeCellRangeDelete({ source, gridSelection }) {

    }
});
ParameterTypeDescription
sourceGrid

Owner grid

gridSelection(GridLocation|Model)[]

An array of cell selectors or records that will have their values deleted (the records themselves will not get deleted, only visible column values).

Called for each selected record on the owning Grid before editing a range of selected cell values

new CellEdit({
    onBeforeCellRangeEdit({ record, field, value }) {

    }
});
ParameterTypeDescription
recordModel

Current selected record from the range

fieldString

The field being changed

value*

The value being set

Called on the owning Grid before the cell editing is finished, return false to signal that the value is invalid and editing should not be finalized.

new CellEdit({
    onBeforeFinishCellEdit({ grid, editorContext }) {

    }
});
ParameterTypeDescription
gridGrid

Target grid

editorContextCellEditorContext

Editing context

Called on the owning Grid when editing is cancelled

new CellEdit({
    onCancelCellEdit({ source, editorContext, event }) {

    }
});
ParameterTypeDescription
sourceGrid

Owner grid

editorContextGridLocation

Editing context

eventEvent

Included if the cancellation was triggered by a DOM event

Called on the owning Grid when cell editing is finished

new CellEdit({
    onFinishCellEdit({ grid, editorContext }) {

    }
});
ParameterTypeDescription
gridGrid

Target grid

editorContextCellEditorContext

Editing context

Called on the owning Grid when editing starts

new CellEdit({
    onStartCellEdit({ source, editorContext }) {

    }
});
ParameterTypeDescription
sourceGrid

Owner grid

editorContextCellEditorContext

Editing context

onDestroyEvents
onDisableInstancePlugin
onEnableInstancePlugin

Typedefs

3

Cell editing context

ParameterTypeDescription
editorField

The input field that the column is configured with (see field). This property may be replaced to be a different field in the handler, to take effect just for the impending edit

ParameterTypeDescription
columnColumn

Target column

recordModel

Target record

cellHTMLElement

Target cell

finalizefunction

An async function may be injected into this property, which performs asynchronous finalization tasks such as complex validation of confirmation. The value true or false must be returned

finalize.contextObject

An object describing the editing context upon requested completion of the edit

value*

Cell value

oldValue*

The old value