Cell Editing
Cell Renderer's are for displaying data and Cell Editors are for editing data.
If your application is for showing data only, such as a reporting application, then you will not
need to use cell editors. If you are editing your data like a spreadsheet, then you will
need Cell Editors to do the editing.
Remember Cell Editing works with all frameworks eg Angular and React as well as plain JavaScript.
You configure cell editors as part of the column definition and can be one of the following:
undefined / null: The grid uses the default text cell editor.
-
string: The name of a cell renderer registered with the grid.
Class: Provide your own cell renderer component directly without registering.
Enabling editing in a column
The simplest way to enable editing is by providing colDef.editable=true by doing so all the cells
in the column will be editable.
It is possible to have only a few cells in a column editable, to do so, instead of colDef.editable=true,
you can specify a callback that will get called for each cell displayed for that column. If you return true the
cell will be editable. The params for the callback are:
| node |
The RowNode of the row being rendered. |
| column |
The column been rendered (in ag-Grid, each colDef is wrapped by a Column). |
| colDef |
The colDef been rendered. |
| context |
The context as set on the gridOptions. |
| api |
A reference to the grid api. |
| columnApi |
A reference to the column api. |
Default Editing
To get simple string editing, you do not need to provide an editor. The grid by default allows simple
string editing on cells. The default editor is used if you do not provide a cell editor.
Start Editing
If you have colDef.editable=true set for a column then editing will start upon any of the following:
Editing can start in the following ways:
- Edit Key Pressed: One of the following is pressed: Enter, F2, Backspace, Delete. If this
happens then params.keyPress will contain the key code of the key that started the edit. The default editor
will clear the contents of the cell if Backspace or Delete are pressed.
- Printable Key Pressed: Any of the following characters are pressed:
"e;qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890!"£$%^&*()_+-=[];\'#,./\|<>?:@~{}"e;
If this happens then params.charPress will contain the character that started the edit. The default editor
places this character into the edit field so that the user experience is they are typing into the cell.
- Mouse Double Click: If the mouse is double clicked. There is a grid property
singleClickEdit
that will allow single click to start editing instead of double click. Another property suppressClickEdit
will prevent both single click and double click from starting the edit - use this if you want to have
your own way of starting editing only, such as clicking a button in your custom cell renderer.
- api.startEditingCell(): If you call
startEditingCell() on the grid API
Stop / End Editing
The grid will stop editing when any of the following happen:
- Callback stopEditing: The callback
stopEditing (from the params above) gets called by the
editor. This is how your cell editor informs the grid to stop editing.
- Other Cell Focus: If focus in the grid goes to another cell, the editing will stop.
- Enter Key Down: If the grid receives an 'Enter' key press event on the cell. If you do NOT
want to stop editing when Enter is pressed, then listen for the event and stop propagation so the grid
does not act on the event.
- Escape Key Down: Similar to Enter, if Escape key is pressed, editing will stop. Unlike Enter,
Escape action will not take the new value, it will discard changes.
- Tab Key Down: Editing will stop, accepting changes, and editing will move to the next cell, or
the previous cell if 'shift' is also pressed.
- Navigation Key Down: Editing will stop, accepting changes, and editing will move to the next cell
in the direction of the navigation key.
- Popup Editor Closed: If using popup editor, the popup is configured to close if you click
outside the editor. Closing the popup triggers the grid to stop editing.
- gridApi.stopEditing(): If you call
stopEditing() on the grid API.
Popup vs In Cell
An editor can be in a popup or in cell.
In Cell
In Cell editing means the contents of the cell will be cleared and the editor will appear
inside the cell. The editor will be constrained to the boundaries of the cell, if it is larger
that the provided area it will be clipped. When editing is finished, the editor will be removed
and the renderer will be placed back inside the cell again.
Popup
If you want your editor to appear in a popup (such as a dropdown list), then you can have it appear
in a popup. The popup will behave like a menu in that any mouse interaction outside of the popup
will close the popup. The popup will appear over the cell, however it will not change the contents
of the cell. Behind the popup the cell will remain intact until after editing is finished which
will result in the cell being refreshed.
From a lifecycle and behaviour point of view, 'in cell' and 'popup' have no impact on the editor. So you
can create a cell editor and change this property and observe how your editor behaves in each way.
To have an editor appear in a popup, have the isPopup() method return true. If you want editing
to be done within a cell, either return false or don't provide this method at all.
Tab Navigation
While editing, if you hit tab, the editing will stop on the current cell and start on the next cell.
If you hold down shift+tab, the same will happen except the previous cell will start editing rather than
the next. This is in line with editing data in Excel.
The next and previous cells can also be navigated using the API functions api.tabToNextCell()
and api.tabToPreviousCell(). Both of these methods will return true if the navigation was
successful, otherwise false.
Value Parser and Value Setter
Value setter and value parsers are the inverse of a
value getters and formatters. If you want to parse the data, or set the value into your data in
ways other than just using the field, see the sections
Value setter and value parsers.
Event: Cell Value Changed
After a cell has been changed with default editing (ie not your own custom cell renderer),
then cellValueChanged event is fired. You can listen for this event in the normal
way, or additionally you can add a onCellValueChanged() callback to the colDef.
This is used if your application needs to do something after a value has been changed.
The cellValueChanged event contains the same parameters as the ValueSetter with one difference,
the newValue. If 'field' is in the column definition, the newValue contains the value
in the data after the edit. So for example, if the onCellValueChanged converts the provided
string value into a number, then newValue for ValueSetter will have the string, and
newValue for onCellValueChanged will have the number.
Editing API
The grid has the following API methods for editing:
-
startEditingCell(params): Starts editing the provided cell. If another cell is editing,
the editing will be stopped in that other cell. Parameters are as follows:
- rowIndex: The row index of the row to start editing.
- colKey: The column key of the column to start editing.
- rowPinned: Set to 'top' or 'bottom' to started editing a pinned row.
- keyPress, charPress: The keyPress and charPress that are passed to the cell editor.
-
stopEditing(cancel): If the grid is editing then editing is stopped. Passing
cancel=true will keep the cells original value and passing cancel=false
will take the latest value from the cell editor.
-
getEditingCells(): If the grid is editing, returns back details of the editing cell(s).
The result is an array of objects. If only one cell is editing (the default) then the array will have
one entry. If multiple cells are editing (eg Full Row Edit) then the
array contains all editing cells.
Below is a code example of using the editing API methods.
// start editing country cell on first row
api.startEditing({
rowIndex: 0,
colKey: 'country'
});
// stop editing
api.stopEditing();
// print details of editing cell
var cellDefs = gridOptions.api.getEditingCells();
cellDefs.forEach( function(cellDef) {
console.log(cellDef.rowIndex);
console.log(cellDef.column.getId());
console.log(cellDef.floating);
});
Start / Stop Editing Events
The following events are fired as editing starts and stops:
cellEditingStarted: editing has started on a cell.
cellEditingStopped: editing has stopped on a row.
rowEditingStarted: editing has started on a row. Only for full row editing.
rowEditingStopped: editing has stopped on a row. Only for full row editing.
Cell Editing Example
The example below illustrates different parts of the editing API. Each button starts
editing the 'Last Name' column of the first row with the following differences:
-
edit(): Normal editing start.
-
edit(Delete): Edit as if delete button was pressed (clears contents first).
-
edit('T'): Edit as if 'T' was pressed (places 'T' into cell).
-
edit(top): Edits top pinned row.
-
edit(bottom): Edits bottom pinned row.
The example then demonstrates the following buttons for edit navigation:
-
stop(): Stops editing.
-
next(): Edits the next cell.
-
previous(): Edits the previous cell.
Finally the example demonstrates querying what cell is editing:
-
which(): If the grid is editing, prints to the console which cell is in edit mode.
Many Editors One Column
It is also possible to use different editors for different rows in the same column.
Typically an application might check the rows contents and choose and editor accordingly.
To configure this set colDef.cellEditorSelector
to a function that returns the name of the component to be used as an editor
and optionally the custom params to be passed into it
The parameters that these functions will receive are:
interface DynamicComponentParams {
data: any,
node: RowNode,
colDef: ColDef,
column: Column,
rowIndex: number,
api: GridApi,
columnApi: ColumnApi
}
The following example illustrates how to use different editors and parameters in the same column. Note that:
- The column 'Value' holds data of different types as shown in the column 'Type' (numbers/genders/moods).
colDef.cellEditorSelector is a function that returns the name of the component to use to edit based on the
type of data for that row
cellEditorSelector:function (params){
if (params.data.type === 'age') return {
component: 'numericCellEditor'
};
if (params.data.type === 'gender') return {
component: 'agRichSelect',
params: {values: ['Male', 'Female']}
};
if (params.data.type === 'mood') return {
component: 'agRichSelect'
};
return null;
}
-
Edit a cell by double clicking to observe the different editors used.
Provided Cell Editors
The grid, out of the box, comes with the following editors:
agTextCellEditor: Simple text editor that uses standard HTML Input. This is the default.
agPopupTextCellEditor: Same as 'text' but as popup.
agLargeTextCellEditor: A text popup that for inputting larger, multi-line text.
agSelectCellEditor: Simple editor that uses standard HTML Select.
agPopupSelectCellEditor: Same as 'select' but as popup.
agRichSelectCellEditor (ag-Grid-Enterprise only): - A rich select popup that uses row virtualisation
agTextCellEditor / agPopupTextCellEditor
Simple text editors that use the standard HTML 'input' tag. agTextCellEditor is the default
used if you do not explicitly set a cell editor.
The only parameter for text cell editors is useFormatter. If set to true then the
grid will use the provided colDef.cellFormatter if one is provided.
agLargeTextCellEditor
Simple editor that uses the standard HTML 'textarea' tag.
The agLargeTextCellEditor takes the following parameters:
-
maxLength: Max number of characters to allow. Default is 200.
-
rows: Number of character rows to display. Default is 10.
-
cols: Number of character columns to display. Default is 60.
agSelectCellEditor / agPopupSelectCellEditor
Simple editors that use standard HTML 'select' tag.
The only parameter for text cell editors is values. Use this to provide a list of
values to the cell editor.
colDef.cellEditor = 'agSelectCellEditor';
colDef.cellEditorParams = {
values: ['English', 'Spanish', 'French', 'Portuguese', '(other)']
}
We have found the standard HTML select to behave odd when in the grid. This is because the browser
doesn't have a great API for opening and closing the select's popup. We advise you don't use
it unless you have to - that is we advise against agSelectCellEditor and agPopupSelectCellEditor as
they give poor user experience, especially if using keyboard navigation. If using ag-Grid Enterprise,
then you should use the provided agRichSelectCellEditor.
agRichSelectCellEditor
Available in ag-Grid Enterprise only. An alternative to using the browsers 'select' tag for drop downs
inside the grid.
The agRichSelectCellEditor has the following benefits of the browsers 'select' tag:
- Uses DOM row visualisation so very large lists can be displayed.
- Integrates with the grid perfectly, no glitches as seen with the standard select.
- Uses HTML to render the values - you can provide cell renderers to cusomise what each value looks like.
The agRichSelectCellEditor takes the following parameters:
-
values: List of values to be selected from.
-
cellHeight: The row height, in pixels, of each value.
-
formatValue: A callback function that allows you to change the displayed value for simple data.
-
cellRenderer: The cell renderer to use to draw each value. Cell renderers are useful to rendering rich
html values, or when processing complex data.
See Cell Rendering Components
for creating custom cell renderers.
Dynamic Parameters
Parameters for cell editors can be dynamic to allow different selections based on what cell is getting edited.
For example you might have a 'City' column that has values based on the 'Country' column. To do this,
provide a function that returns parameters for the property cellEditorParams
cellEditorParams: function(params) {
var selectedCountry = params.data.country;
if (selectedCountry==='Ireland') {
return {
values: ['Dublin','Cork','Galway']
};
} else {
return {
values: ['New York','Los Angeles','Chicago','Houston']
};
}
}
Example Rich Cell Editor / Dynamic Parameters
Below shows an example with dynamic editor parameters. The following can be noted:
- Column Gender uses a cell renderer for both the grid and the editor.
- Column Country allows country selection, with
cellHeight being used to make each entry 50px height.
If the selection doesn't match the city, the city cell is cleared.
- Column City uses dynamic parameters to display values for the selected country, and uses
formatValue
to add the selected city's country as a suffix.
- Column Address uses the rich text area editor.
Enter Key Navigation
By default pressing Enter will start editing on a cell, or stop editing
on an editing cell. It will not navigate to the cell below.
To allow consistency with Excel the grid has the following properties:
enterMovesDown: Set to true to have Enter key move focus to the cell
below if not editing. The default is Enter key starts editing the currently focused cell.
enterMovesDownAfterEdit: Set to true to have Enter key move
focus to the cell below after Enter is pressed while editing. The default
is editing will stop and focus will remain on the editing cell.
The example below demonstrates the focus moving down when Enter is pressed.
Datepicker Cell Editing Example
The example below illustrates:
- 'Date' column uses a Component cell editor that allows you to pick a date using jQuery UI Datepicker.
Full Row Editing
Full row editing is for when you want all cells in the row to become editable at the same time.
This gives the impression to the user that the record the row represents is getting edited.
To enable full row editing, set the grid option editType = 'fullRow'.
If using custom cell editors, the cell editors will work in the exact same way with the
following additions:
focusIn: If your cell editor has a focusIn() method, it will get called when the
user tabs into the cell. This should be used to put the focus on the particular item
to be focused, eg the textfield within your cell editor.
focusOut: If your cell editor has a focusOut() method, it will get called when the
user tabs out of the cell. No intended use for this, is just there to compliment the
focusIn() method, maybe you will have a reason to use it.
Events: When a row stops editing, the cellValueChanged event gets called
for each column and rowValueChanged gets called once for the row.
Full Row Edit and Popup Editors
Full row editing is not compatible with popup editors. This is because a) the grid would look
confusing to pop up an editor for each cell in the row at the same time and b) the complexity
of navigation and popup is almost impossible to model - thus the grid and your application code
would be to messy and very error prone. If you are using full row edit, then you are blocked
from using popup editors.
This does not mean that you cannot show a popup from your 'in cell' editor - you are free to
do that - however the responsibility of showing and hiding the popup belongs with your editor.
You may want to use the grids focus events to hide the popups when the user tabs or clicks out
of the cell.
Full Row Edit Example
The example below shows full row editing. In addition to standard full row editing,
the following should also be noted:
-
The 'Price' column has a custom editor demonstrating how you should implement
the
focusIn() method. Both focusIn() and focusOut() for this
editor are logged to the console.
-
The 'Suppress Navigable' column is not navigable using tab. In other words,
when tabbing around the grid, you cannot tab onto this cel.
-
The 'Not Editable' column is not editable, so when the row goes into edit mode,
this column is not impacted. Also when editing, this column is not navigated to
when tabbing.
-
The button will start editing line two. It uses the api to start editing a cell,
however the result is the whole row will become editable starting with the
specified cell.
-
cellValueChanged and rowValueChanged events are logged to console.
-
The CSS class
ag-row-editing changes the background color to highlight
the editing row.
Single Click, Double Click, No Click Editing
Double Click Editing
The default is for the grid to enter editing when you double click on a cell.
Single Click Editing
To change the default so that a single click starts editing, set the property gridOptions.singleClickEdit=true.
This is useful when you want a cell to enter edit mode as soon as you click on it, similar to the experience
you get when inside Excel.
It is also possible to define single click editing on a per column basis using: colDef.singleClickEdit = true.
No Click Editing
To change the default so that neither single or double click starts editing, set the property
suppressClickEdit=true. This is useful when you want to start the editing in another way,
such as including a button in your cell renderer.
The grid below has singleClickEdit=true so that editing will start on a cell when you single click on it.
The grid below has suppressClickEdit=true so that clicking doesn't started editing. The grid configures a cellRenderer with a button to start editing.
Stop Editing When Grid Loses Focus
By default, the grid will not stop editing the currently editing cell when the grid
loses focus. This can be bad if, for example, you have a save button, and you need
the grid to stop editing before you execute your save function (eg you want to make
sure the edit is saved into the grids state).
If you want the grid to stop editing when focus leaves, set the grid property
stopEditingWhenGridLosesFocus=true.
By default, the grid not stop editing if you focus outside. The default is
good for custom popup cell editors as these can have the focus leave the grid
(eg if using a popup calendar widget). This would be bad as the grid would stop
editing as soon as your external popup appeared.
The example below shows the editing with stopEditingWhenGridLosesFocus=true.
Notice the following:
-
Double click to start editing 'Age', then click outside the grid (on the 'Dummy Save'
button, or the dummy text field) and the grid will stop editing.
-
Double click to start editing 'Year', a custom popup editor appears, you can click
anywhere on the popup editor, but once you click outside the editor, the popup closes.
Cell Editing can also be done via Cell Editor Components - please see
Cell Editor Components for more information.
Controlling keyboard while editing
While editing, the grid will listen to navigation events coming from the keyboard, this includes navigate to next cell,
next row... If you want to avoid this events from being consumed by the grid you can do so by configuring
colDef.suppressKeyboardEvent.
The following example shows a simple example where each cell contains a number and the arrows are used to manipulate
its value.
Note how the arrows are used to increase or decrease the value of the cell while editing and they are not used for
navigation
suppressKeyboardEvent: function(event){
if (event.editing) return true;
}