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 |
Ctrl is the equivalent to Command and Alt
is the equivalent to Option for Mac userstrue.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.
//<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
Configs
22Other
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.
Set to true to select the field text when editing starts
What action should be taken when focus moves leaves the cell editor, for example when clicking outside.
May be 'complete' or 'cancel'.
See Keyboard shortcuts for details
If set to true (which is default) this will make it possible to edit current column in multiple rows
simultaneously.
This is achieved by:
- Select multiple rows or row's cells
- Start editing simultaneously as selecting the last row or cell
- 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.
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.
Misc
Properties
23
Properties
23Common
Class hierarchy
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.
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.
Functions
33
Functions
33Editing
Cancel editing, hides the editor.
This function is exposed on Grid and can thus be called as grid.cancelEditing(...)
| Parameter | Type | Description |
|---|---|---|
silent | Boolean | Pass true to prevent method from firing event |
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(...)
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(...)
| Parameter | Type | Description |
|---|---|---|
cellContext | GridLocationConfig | Cell specified in format { id: 'x', columnId/column/field: 'xxx' }. See getCell for details. |
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.
| Parameter | Type | Description |
|---|---|---|
options | Object | An options object for what to show. |
options.title | String | The title to show in the dialog header. |
options.message | String | The message to show in the dialog body. |
options.cancelButton | String | Object | A text or a config object to apply to the Cancel button. |
options.okButton | String | Object | A text or config object to apply to the OK button. |
Configuration
Events
Misc
Events
13
Events
13Fires 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Grid | Owner grid |
editorContext | GridLocation | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Grid | Owner grid |
editorContext | CellEditorContext | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Grid | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
record | Model | Current selected record from the range |
field | String | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
grid | Grid | Target grid |
editorContext | CellEditorContext | Editing context |
Fires on the owning Grid when editing is cancelled
// Adding a listener using the "on" method
cellEdit.on('cancelCellEdit', ({ source, editorContext, event }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Grid | Owner grid |
editorContext | GridLocation | Editing context |
event | Event | 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 }) => {
});| Parameter | Type | Description |
|---|---|---|
grid | Grid | Target grid |
editorContext | CellEditorContext | Editing context |
Fires on the owning Grid when editing starts
// Adding a listener using the "on" method
cellEdit.on('startCellEdit', ({ source, editorContext }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Grid | Owner grid |
editorContext | CellEditorContext | Editing context |
Event handlers
13
Event handlers
13Called on the owning Grid before the cell editing is canceled, return false to prevent cancellation.
new CellEdit({
onBeforeCancelCellEdit({ source, editorContext }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Grid | Owner grid |
editorContext | GridLocation | Editing context |
Called on the owning Grid before editing starts, return false to prevent editing
new CellEdit({
onBeforeCellEditStart({ source, editorContext }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Grid | Owner grid |
editorContext | CellEditorContext | 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 }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Grid | 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 }) {
}
});| Parameter | Type | Description |
|---|---|---|
record | Model | Current selected record from the range |
field | String | 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 }) {
}
});| Parameter | Type | Description |
|---|---|---|
grid | Grid | Target grid |
editorContext | CellEditorContext | Editing context |
Called on the owning Grid when editing is cancelled
new CellEdit({
onCancelCellEdit({ source, editorContext, event }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Grid | Owner grid |
editorContext | GridLocation | Editing context |
event | Event | 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 }) {
}
});| Parameter | Type | Description |
|---|---|---|
grid | Grid | Target grid |
editorContext | CellEditorContext | Editing context |
Called on the owning Grid when editing starts
new CellEdit({
onStartCellEdit({ source, editorContext }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Grid | Owner grid |
editorContext | CellEditorContext | Editing context |
Typedefs
3
Typedefs
3Cell editing context
| Parameter | Type | Description |
|---|---|---|
editor | Field | 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 |
| Parameter | Type | Description |
|---|---|---|
column | Column | Target column |
record | Model | Target record |
cell | HTMLElement | Target cell |
finalize | function | An async function may be injected into this property, which performs asynchronous
finalization tasks such as complex validation of confirmation. The value |
finalize.context | Object | An object describing the editing context upon requested completion of the edit |
value | * | Cell value |
oldValue | * | The old value |