Editing Data in AdapTable

Editing Data in AdapTable

AdapTable offers a wealth of features and functionalities designed to enable quick, safe and audited data entry; this blog post describes a demo app that contains many of these.

12 min readApril 13, 2026

AdapTable boasts a wealth of features that facilitate swift, safe and audited data entry.

These provide our users with significant competitive advantage, helping them to edit data faster, more intuitively and more accurately than their competitors.

This blog post provides a small demo (built using the vanilla/TypeScript version of AdapTable) which contains many of the editing-related functionalities provided in AdapTable including:

Important

The demo uses only existing AdapTable functionality, UI components and API methods

FunctionalityDetails
Smart EditEdits multiple numeric cells using single operation
Bulk UpdateUpdates many cells to same value
ShortcutSets mathematical operations when shortcut key is clicked
Plus Minus"Nudge Rules" for when + or - are pressed on the keyboard
Cell EditorsSpecialist Editors - Select, Percent, Numeric & Date Picker
Action ColumnSpecial columns containing buttons (which can be used when editing)
Row FormsSpecial forms designed for bespoke row editing (and creating)
Cell EditabilityConfigure which cells can be edited
Editable Cell StylingCustom style Editable, ReadOnly and Edited Cells
Data ValidationValidate data entry (on both Client and Server)
Change HistoryFull recorded history of all data edits

Note

  • We have enabled Flashing Cells in this demo to make it easier to see which Cells are being edited
  • Additionally we have provided Styles for Editable Cells and Edited Cells (see below for more details)
Editing Data in AdapTable (v22)

Smart Edit

The Smart Edit module allows users to apply a single edit to multiple, numeric cells, using one of the 4 mathematical Smart Edit Operations supplied by AdapTable:

  • Addition
  • Subtraction
  • Multiplication
  • Division

In addition developers are able to provide Custom Smart Edit Operations if required.

We do that in this demo by providing a Power operation:

editOptions: {
  smartEditCustomOperations: [
  {
    name: 'Power',
    operation: (context: SmartEditOperationContext) => {
      return Math.pow(context.currentCell.rawValue, context.smartEditValue);
    },
  }],
}

We leverage the Adaptable Ready Event - which fires when AdapTable has initialised - to make Power the current operation and to set the smart edit value to 2:

export const onAdaptableReady = ({adaptableApi}: AdaptableReadyInfo) => {
  adaptableApi.smartEditApi.setCustomSmartEditOperation('Power');
  adaptableApi.smartEditApi.setSmartEditValue(2);
};

Bulk Update

AdapTable also provides a Bulk Update module which facilitates updating multiple cells in a column to the same value in a single step.

Note

  • Bullk Update controls display a dropdown listing all distinct column values to facilitate quick editing
  • Alternatively, run-time users can update the cells to a new value (which is not currently in the Grid)

Shortcut

Another data entry Module provided by AdapTable is Shortcuts.

Hint

Shortcuts help to avoid "fat finger" issues by providing an easy way to accurately edit numeric data

A Shortcut consists of an alphabet keystroke which when entered into a numeric cell automatically converts into a mathemetical operation using the existing cell contents.

In our Demo we added a Shortcut of 'K' multiplying values in Github Watchers column by 1000:

Shortcut: {
  Shortcuts: [
    {
      Name: 'shortcut-K-multiply-1000',
      Scope: { ColumnIds: ['github_watchers'] },
      ShortcutKey: 'K',
      ShortcutOperation: 'Multiply',
      ShortcutValue: 1000,
    }],
},

Plus Minus

The Plus Minus module is used to update numeric cells, this time in response to keyboard input:

  • the plus(+) keyboard key causes an increment of the cell's value
  • the minus(-) keyboard key causes a decrement of the cell's value

Hint

This is ideal for situations where data needs to be edited incredibly quickly (e.g. if marking to market)

It is possible to provide a Nudge Condition, so the Plus / Minus only operates if the rule's evaluation returns true.

In our demo we have applied 2 Plus Minus Nudge Rules, both to the Github Watchers column:

  • Increase / Decrease by 10 if the Language is TypeScript - this rule will get evaluated first
  • Increase / Decrease by 2 - this rule will get evaluated only if rule above returns false
PlusMinus: {
  PlusMinusNudges: [
    {
      Name: 'plusMinus-github_watchers-TypeScript',
      Scope: { ColumnIds: ['github_watchers'] },
      Rule: { BooleanExpression: '[language] = "TypeScript"' },
      NudgeValue: 10,
    },
    {
      Name: 'plusMinus-github_watchers-Normal',
      Scope: { ColumnIds: ['github_watchers'] },
      NudgeValue: 2,
    }],
},

Action Column

The functionality we provided in the Plus Minus rules can also be achieved using Action Columns.

Action Columns are special columns which display a Button(s) with a user-defined action.

Hint

  • The buttons in the Action Column can do anything and are not limited to editing
  • However, a frequent Action Column use case is to edit a cell in an adjacent Column

Our demo contains an Update Stars Action Column which contains 2 Up and Down buttons that update the Github Stars column (using similar rules as provided for Plus Minus Nudges above).

actionColumnOptions: {
  actionColumns: [
    {
      columnId: 'update_stars',
      friendlyName: 'Update Stars',
      actionColumnButton: [
        {
          label: 'Up',
          buttonStyle: { variant: 'outlined', tone: 'info' },
          onClick: (button: ActionColumnButton<ActionColumnContext>, context: ActionColumnContext) => {
            const rowData: WebFramework = context.rowNode?.data;
            const increment = rowData.language == 'TypeScript' ? 10 : 2;
            const cellUpdateRequest: CellUpdateRequest = {
              columnId: 'github_stars',
              newValue: rowData.github_stars + increment,
              primaryKeyValue: context.primaryKeyValue,
              rowNode: context.rowNode,
            };
            context.adaptableApi.gridApi.setCellValue(cellUpdateRequest);
          },
        },
        {
          label: 'Down',
          buttonStyle: { variant: 'outlined', tone: 'warning' },
          onClick: ( button: ActionColumnButton<ActionColumnContext>, context: ActionColumnContext) => {
            const rowData: WebFramework = context.rowNode?.data;
            const decrement = rowData.language == 'TypeScript' ? 10 : 2;
            const cellUpdateRequest: CellUpdateRequest = {
              columnId: 'github_stars',
              newValue: rowData.github_stars - decrement,
              primaryKeyValue: context.primaryKeyValue,
              rowNode: context.rowNode,
            };
            context.adaptableApi.gridApi.setCellValue(cellUpdateRequest);
          },
        }],
    },],
},

Cell Editors

AdapTable provides 4 Cell Editors so that data can can be quickly and safely entered into AG Grid:

EditorWhich ColumnsWhen Used
Select (Dropdown) EditorAllIf configured in EditOptions
Numeric Cell EditorNumericAlways
Date PickerDateAlways
Percentage Cell EditorNumericWith % Rendering

In the demo we display the Select Editor when editing the Language and License columns:

editOptions: {
  showSelectCellEditor: context => {
    return (context.column.columnId === 'language' || context.column.columnId === 'license');
  },
}

Note

The Numeric Cell Editor and Date Picker are also available in the demo as they are the default editors

Custom Edit Values

By default the Select Editor will display all the distinct values in the Column, and the run-time user simply needs to select the required value from the list that automatically appears.

However it is possible to provide a custom set of values to display in the select editor if required.

In the demo we provide extra options to display in the Language Column's Select Editor:

editOptions: {
  customEditColumnValues: (customEditColumnValuesContext: CustomEditColumnValuesContext) => {
      if (customEditColumnValuesContext.column.columnId === "language") {
        const extraValues = [
          { label: "Python", value: "Python" },
          { label: "XML", value: "XML" },
          { label: "CSS", value: "CSS" },
        ];
        return Array.from(
          new Map(
            [
              ...customEditColumnValuesContext.defaultValues,
              ...extraValues,
            ].map((item) => [item.label, item])
          ).values()
        );
      }
      return customEditColumnValuesContext.defaultValues;
    },
}

Note

  • The additional Language Column options are also available when using Bulk Update components
  • Likewise, you will see these values when editing the Column in a Row Form (see below)

Row Forms

AdapTable provides Row Forms as an alternative to inline data editing.

Row Forms are popups which display all editable fields in a row, togther with the appropriate cell editor for that field.

Hint

  • Row Forms are useful if wanting to perform particular actions or validation before committing edits
  • They also allow users to batch all the edits for a row into a single update action

Our demo includes an Edit Row Form, which is accessed via an edit Action Column Command.

actionColumnOptions: {
  actionColumns: [{
      columnId: 'edit',
      friendlyName: 'Actions',
      actionColumnButton: [{
          command: 'edit',
          label: ' Edit',
          buttonStyle: { variant: 'text', tone: 'success' },
        }],
    }],
},

The configuration for the Row Form sets 3 things:

  • auto-handles saving the Row (there is an option to handle the Save in a custom fashion)
  • we dont disable in line editing (normally set to true but we want to show both in our demo)
  • hides the id Column from the Row Form (as the user doesn't need to see it)
rowFormOptions: {
  autoHandle: true,
  disableInlineEditing: false,
  includeColumnInRowForm: (rowFormColumnContext: RowFormColumnContext) => {
    return rowFormColumnContext.adaptableColumn.columnId !== 'id';
  },
},

Setting Cell Editability

AdapTable respects AG Grid rules regarding whether cells are editable or readonly.

But it also allows developers to override this and set editability at Column or Cell level.

In our demo we have set the Language and Issue Change Columns to be readonly, but provide exceptions where Language is not "HTML" and Issue Change is positive.

editOptions: {
  isCellEditable: (cellEditableContext: CellEditableContext) => {
    const gridCell: GridCell = cellEditableContext.gridCell;
    if (gridCell.column.columnId === 'language' && gridCell.displayValue !== 'HTML') {
      return true;
    }
    if (gridCell.column.columnId === 'week_issue_change' && gridCell.rawValue > 0) {
      return true;
    }
    return cellEditableContext.defaultColDefEditableValue;
  },
},
We set which cells are editable and provide an Editable Cell Style (see below)
We set which cells are editable and provide an Editable Cell Style (see below)

Styling Editable Cells

AdapTable allows developers to visually indicate cell editability information to runtime users.

There are 3 similar functions which allow styles to be provided for:

  • editable Cells
  • readonly Cells
  • edited Cells

In our demo we provide 2 Styles: one for editable Cells, and one for edited Cells:

  userInterfaceOptions: {
    editableCellStyle: {
      BorderColor: 'LightYellow',
      BorderRadius: 6,
    },
    editedCellStyle: {
      BackColor: 'LightYellow',
      ForeColor: 'Brown',
    },
  },
We set an edited cell style - seen via the 4 edited cells
We set an edited cell style - seen via the 4 edited cells

Validation

AdapTable providdes 2 main types of Data Validation:

In our demo we provide one example of each Validation, using the Issue Change Column:

  • Client Side Validation - value cannot be negative (if so, a warning appears)
Alert: {
  AlertDefinitions: [{
      Name: 'alert-week_issue_change_negative',
      Scope: { ColumnIds: ['week_issue_change'] },
      Rule: { Predicates: [{ PredicateId: 'Negative' }]},
      AlertProperties: {
        PreventEdit: true,
        DisplayNotification: true,
      },
      MessageType: 'Error',
      MessageText: 'Week Issue Change cannot be negative!',
    }],
},
  • Server Side Validation - value cannot be greater than 60 (if so, we set edited value to 60)
editOptions: { // would typically happen on the server, rather than client...
  validateOnServer: (serverValidationContext: ServerValidationContext) => {
    return new Promise((resolve, reject) => {
      const cellDataChangedInfo = serverValidationContext.cellDataChangedInfo;
      if (cellDataChangedInfo.column.columnId == 'week_issue_change') {
        if (cellDataChangedInfo.newValue > 60) {
          resolve({
            newCellValue: 60,
            validationMessage: 'Week Issue Change cannot be greater than 60',
            validationHeader: 'Too High',
            messageType: 'Error',
          });
          return;
        }
      }
      resolve({});
    });
  },
},

Data Change History

AdapTable can display a list of all data changes that have happened in the current session.

In our demo we have set the (very configurable) Data Change History Monitor to:

  • be turned on by default (so all data changes are automatically tracked)
  • provided with an "undo" button which, when clicked, will undo the change
dataChangeHistoryOptions: {
  activeByDefault: true,
  changeHistoryButton: [{
      action: 'undo',
      label: (button, context) => { return context.isGroupNode ? 'Undo Group' : 'Undo';  },
      buttonStyle: { variant: 'raised', tone: 'accent' },
    }],
},

Undoing Data Changes

It's also possible for run-time users to undo edits directly in the Grid, without needing to open the Data Change History Monitor.

Find Out More

See the Undoing Data Edits Blog Post for more details on how to achieve this

In our demo we add a Custom Context Menu Item which appears only in cells which have been edited, and allows the run-time user to undo the edit directly.

contextMenuOptions: {
  customContextMenu: (context: CustomContextMenuContext) => {
    const { defaultAgGridMenuStructure, defaultAdaptableMenuStructure, gridCell, adaptableApi } = context;
    const undoEditMenuItem: UserContextMenuItem = {
      menuType: 'User',
      label: 'Undo Edit',
      icon: { name: 'undo' },
      hidden: !adaptableApi.gridApi.isCellEdited(gridCell),
      onClick: () => {
        const dataChange = adaptableApi.dataChangeHistoryApi.getDataChangeForGridCell(gridCell);
        adaptableApi.dataChangeHistoryApi.undoDataChangeHistoryEntry(dataChange);
        adaptableApi.gridApi.refreshGridCell(gridCell);
      },
    };
    return [ undoEditMenuItem, ...defaultAgGridMenuStructure, '-', ...defaultAdaptableMenuStructure ];
}},

Additionally we provide a Custom Toolbar which contains an Adaptable Button that clears all Edits that have been made:

dashboardOptions: {
  customToolbars: [
    {
      name: 'ButtonToolbar',
      title: 'Buttons',
      toolbarButtons: [
        {
          label: 'Undo All Edits',
          onClick: (btn: AdaptableButton<CustomToolbarButtonContext>, context: CustomToolbarButtonContext) => {
            const { adaptableApi } = context;
            const gridCells = adaptableApi.dataChangeHistoryApi.undoAllDataChangeHistoryEntries();
            adaptableApi.gridApi.refreshGridCells(gridCells);
          },
          buttonStyle: { tone: 'info', variant: 'raised' },
        },
      ],
    },
]},