DataGrid Undo/Redo

Undo and redo grid settings and saved row edits.

Add ngbGridHistory to record filters, sorting, grouping, page size and column layouts. Saved row edits join the same history. Undo restores the previous values or configuration; Redo reapplies the change you undid.

Available in ngbootstrap 2.3.0 and later.

The following example demonstrates

Reversing changes from the grid header toolbar. Sort Customer, then type Pending into the Status filter. Choose Undo twice to return to the starting settings, or Redo to reapply each change. You can also edit a row, save a new Status, and use Undo/Redo to restore and reapply that saved value.

Undo steps: 0 · Redo steps: 0 · Limit: 10 steps

Change a filter or column to begin.

Start editing a row and try Undo: history keeps the current edit and asks you to save or cancel first. After saving, Undo restores the previous row values and Redo reapplies the saved edit.

Add history to your grid

Import the grid, history directive, toolbar and button directives. Project the toolbar inside the grid. Undo and Redo tools find the grid history automatically and manage their disabled state.

      import { Component, signal } from '@angular/core';
import { Datagrid, NgbDataGridHistoryDirective, NgbDataGridHistoryResult, NgbDatagridToolbarComponent, NgbGridUndoToolDirective, NgbGridRedoToolDirective } from '@angular-bootstrap/ngbootstrap';

@Component({
  standalone: true,
  imports: [Datagrid, NgbDataGridHistoryDirective, NgbDatagridToolbarComponent, NgbGridUndoToolDirective, NgbGridRedoToolDirective],
  template: `
    <ngb-datagrid #grid ngbGridHistory [historyLimit]="20"
      (historyKeyboardResult)="announce($event, 'History updated.')"
      [columns]="columns" [data]="rows" [dataOperations]="true" [enableSorting]="true">
      <ngb-datagrid-toolbar [grid]="grid">
        <button ngbGridUndoTool (historyResult)="announce($event, 'Change undone.')">Undo</button>
        <button ngbGridRedoTool (historyResult)="announce($event, 'Change redone.')">Redo</button>
      </ngb-datagrid-toolbar>
    </ngb-datagrid>
    <p role="status">{{ message() }}</p>
  `,
})
export class OrdersPage {
  readonly message = signal('');
  columns = [{ field: 'order', header: 'Order', sortable: true }];
  rows = [{ order: 'ORD-3102' }, { order: 'ORD-3101' }];
  announce(result: NgbDataGridHistoryResult, success: string): void {
    this.message.set(result.success ? success : result.message);
  }
}
    

Customize the toolbar

Buttons are native elements: choose their text, icons, CSS classes, order and accessible labels. Add [disabled]="readOnly" to restrict an action further; an empty history stack always disables its tool. Handle historyResult for announcements or errors. Do not also call undo or redo from a click handler.

      <ngb-datagrid-toolbar [grid]="grid" ariaLabel="Order layout history">
  <button ngbGridUndoTool class="my-history-button" [disabled]="readOnly"
    (historyResult)="announce($event, 'Layout reverted.')">Revert layout</button>
  <button ngbGridRedoTool aria-label="Reapply layout" title="Reapply layout"
    (historyResult)="announce($event, 'Layout reapplied.')">
    <span aria-hidden="true">↷</span>
  </button>
</ngb-datagrid-toolbar>
    

Give icon-only buttons an aria-label and hide decorative icons with aria-hidden="true". The toolbar uses library theme tokens. You can include other tools or keep only Undo and Redo.

How history works

  • History starts after the first browser render and remains in memory until the grid is destroyed.
  • Interactive configuration changes and successful saved-view restores are recorded automatically. Identical settings do not add a step.
  • A new change after Undo discards the Redo stack. The oldest steps are discarded when the limit is reached.
  • A configuration restore emits one dataStateChange. A saved-edit restore emits one rowSave with historyAction set to undo or redo; it does not also trigger a configuration reload.
  • Configuration restores start on page one and respect current column constraints. Saved-edit restores keep the current configuration and page. Failed restores leave both stacks intact.

After changing grid inputs from application code, call history.record() once Angular has applied those inputs. Use history.clear() when switching datasets or when previous layouts should no longer be offered.

Clear history keeps the current settings. The Saved Views control's Reset restores its initial settings. If history is enabled, a Reset that changes the configuration can itself be undone.

API reference

APIPurpose
ngbGridHistoryStandalone directive on an ngb-datagrid. Also its template export name.
ngbGridUndoTool / ngbGridRedoToolNative button directives inside a grid with history. Customize content, classes, disabled input and historyResult output.
historyLimitMaximum undo steps. Defaults to 20; accepts an integer from 1 to 1000.
historyKeyboardDefaults to true when ngbGridHistory is present. Set false to disable grid shortcuts.
historyKeyboardResultEmits the result of a keyboard action. Use it for live announcements and errors.
undo() / redo()Restore one configuration or saved edit and return an NgbDataGridHistoryResult.
canUndo() / canRedo()Read-only signals for button availability.
undoCount() / redoCount()Read-only signals with the available step counts.
ready() / error()Read-only signals for initialization and the latest capture/restore error.
record()Explicitly record application-driven settings. Returns a result.
clear()Discard both stacks and capture the current settings as a new baseline. Returns a result.

Check result.success. Failures include editing, invalid-snapshot, empty-history, not-ready, invalid-state, row-conflict and validation; result.message explains the next step. A successful result lists any removed fields in ignoredFields.

Persisting undone and redone edits

Persist replayed edits through rowSave; historyAction identifies undo or redo. Batch replay uses batchSave instead. Your application handles backend requests and failures.

Use a stable trackBy when replacing row objects. Conflicting changes are rejected. Reload data and clear history after failed saves or when switching datasets.

Supported behavior and limitations

Supported: Grid configuration, applying saved views and saved edits to existing rows across the built-in editing modes. Applied batches replay as one step; custom buttons must use undoAsync() / redoAsync() for them.

Excluded: Unsaved drafts, selection, expanded rows, themes, page number and managing named views. Adding or deleting rows clears history and cannot be undone.

History is bounded and lost on reload. New changes clear redo; configuration replay returns to page one. Row values must use plain objects, arrays, primitives or valid Dates; unsupported values clear history. Custom edit services must preserve original values.

Keyboard accessibility

Adding ngbGridHistory enables shortcuts while focus is inside that grid. Tab to a toolbar button or another grid control first. Shortcuts do not run elsewhere on the page.

  • Ctrl/Cmd + Z: Undo.
  • Ctrl/Cmd + Shift + Z: Redo. Ctrl + Y also works.
  • Tab/Shift + Tab: move between controls. Enter or Space: activate a focused toolbar button.

Inputs, text areas, selects and editable content retain native keyboard behavior, including text undo. Save or cancel an active row editor before replaying grid history. Empty history, held keys and IME composition do not trigger replay.

Set [historyKeyboard]="false" to disable shortcuts, for example when your application supplies its own key bindings. A button's disabled input restricts that button only; also disable shortcuts for a read-only workflow.

Handle (historyKeyboardResult) and button (historyResult) with a visible role="status" message, as this example does. The tools expose their shortcuts through aria-keyshortcuts. Custom icon-only buttons need accessible labels. History does not add spreadsheet-style cell navigation; test custom editors and screen-reader workflows in your application.

This project is not affiliated with ng-bootstrap or ngx-bootstrap. Those projects focus mainly on Bootstrap components for Angular. ngbootstrap focuses on Angular UI for data-heavy apps, especially Data Grid, Angular-native Form Builder, drag and drop workflows, documentation examples, and performance-focused Angular patterns.