---
title: "Highlighting Changes"
framework: angular
version: "36.1.0"
---

# Highlighting Changes

Highlight changes by flashing or animating cells.

#### Animated Flashing Cells

```ts
import { Component } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
import "./styles.css";
import {
  CellStyleModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  HighlightChangesModule,
  ModuleRegistry,
  RowApiModule,
  enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  RowApiModule,
  CellStyleModule,
  ClientSideRowModelModule,
  HighlightChangesModule,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<ag-grid-angular
    style="width: 100%; height: 100%;"
    [columnDefs]="columnDefs"
    [defaultColDef]="defaultColDef"
    [rowData]="rowData"
    (gridReady)="onGridReady($event)"
  /> `,
})
export class AppComponent {
  columnDefs: ColDef[] = [
    { field: "a", enableCellChangeFlash: true },
    { field: "b", enableCellChangeFlash: true },
    { field: "c", cellRenderer: "agAnimateShowChangeCellRenderer" },
    { field: "d", cellRenderer: "agAnimateShowChangeCellRenderer" },
    { field: "e", cellRenderer: "agAnimateSlideCellRenderer" },
    { field: "f", cellRenderer: "agAnimateSlideCellRenderer" },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    cellClass: "align-right",
    valueFormatter: (params) => {
      return formatNumber(params.value);
    },
  };
  rowData: any[] | null = createRowData();

  onGridReady(params: GridReadyEvent) {
    const updateValues = () => {
      const rowCount = params.api!.getDisplayedRowCount();
      // pick 2 cells at random to update
      for (let i = 0; i < 2; i++) {
        const row = Math.floor(window.agRandom() * rowCount);
        const rowNode = params.api!.getDisplayedRowAtIndex(row)!;
        const col = ["a", "b", "c", "d", "e", "f"][
          Math.floor(window.agRandom() * 6)
        ];
        rowNode.setDataValue(col, Math.floor(window.agRandom() * 10000));
      }
    };
    setInterval(updateValues, 250);
  }
}

function formatNumber(number: number) {
  return Math.floor(number).toLocaleString();
}
function createRowData() {
  const rowData = [];
  for (let i = 0; i < 20; i++) {
    rowData.push({
      a: Math.floor(((i + 323) * 145045) % 10000),
      b: Math.floor(((i + 323) * 543020) % 10000),
      c: Math.floor(((i + 323) * 305920) % 10000),
      d: Math.floor(((i + 323) * 204950) % 10000),
      e: Math.floor(((i + 323) * 103059) % 10000),
      f: Math.floor(((i + 323) * 468276) % 10000),
    });
  }
  return rowData;
}
```

[Live example: Animated Flashing Cells](https://www.ag-grid.com/examples/change-cell-renderers/animated-flashing-cells/angular)

The example above shows changing values:

- Columns A and B use [Flashing Cells](https://www.ag-grid.com/angular-data-grid/change-cell-renderers/#flashing-cells).
- Columns C and D use the [Animate Show Change](https://www.ag-grid.com/angular-data-grid/change-cell-renderers/#animate-show-changed-cells) cell renderer.
- Columns E and F use the [Animate Slide Cell](https://www.ag-grid.com/angular-data-grid/change-cell-renderers/#animate-slide-cells) cell renderer.

## Flashing Cells

You can trigger cells to flash either though the Grid API or by enabling cells to flash when the data changes.

### Enable Flashing on Data Change

Set Column attribute `enableCellChangeFlash=true` to flash the cells when data changes.

#### Flashing Data Changes

```ts
import { Component } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
import "./styles.css";
import {
  CellStyleModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  HighlightChangesModule,
  ModuleRegistry,
  RowApiModule,
  enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  RowApiModule,
  HighlightChangesModule,
  CellStyleModule,
  ClientSideRowModelModule,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div style="height: 100%; display: flex; flex-direction: column">
    <div style="margin-bottom: 4px">
      <button (click)="onUpdateSomeValues()">Update Some Data</button>
    </div>
    <div style="flex-grow: 1">
      <ag-grid-angular
        style="width: 100%; height: 100%;"
        [columnDefs]="columnDefs"
        [defaultColDef]="defaultColDef"
        [rowData]="rowData"
        (gridReady)="onGridReady($event)"
      />
    </div>
  </div> `,
})
export class AppComponent {
  private gridApi!: GridApi;

  columnDefs: ColDef[] = [
    { field: "a" },
    { field: "b" },
    { field: "c" },
    { field: "d" },
    { field: "e" },
    { field: "f" },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    cellClass: "align-right",
    enableCellChangeFlash: true,
    valueFormatter: (params) => {
      return formatNumber(params.value);
    },
  };
  rowData: any[] | null = createRowData();

  onUpdateSomeValues() {
    const rowCount = this.gridApi.getDisplayedRowCount();
    // pick 20 cells at random to update
    for (let i = 0; i < 20; i++) {
      const row = Math.floor(window.agRandom() * rowCount);
      const rowNode = this.gridApi.getDisplayedRowAtIndex(row)!;
      const col = ["a", "b", "c", "d", "e", "f"][i % 6];
      rowNode.setDataValue(col, Math.floor(window.agRandom() * 10000));
    }
  }

  onGridReady(params: GridReadyEvent) {
    this.gridApi = params.api;
  }
}

function formatNumber(number: number) {
  return Math.floor(number).toLocaleString();
}
function createRowData() {
  const rowData = [];
  for (let i = 0; i < 20; i++) {
    rowData.push({
      a: Math.floor(((i + 323) * 25435) % 10000),
      b: Math.floor(((i + 323) * 23221) % 10000),
      c: Math.floor(((i + 323) * 468276) % 10000),
      d: 0,
      e: 0,
      f: 0,
    });
  }
  return rowData;
}
```

[Live example: Flashing Data Changes](https://www.ag-grid.com/examples/change-cell-renderers/flashing-data-changes-coldef/angular)

In the example above:

- All columns have `enableCellChangeFlash=true` so changes to the cell values will flash the cell.
- Clicking **Update Some Data** will randomly update some data. The grid will then flash the cells where data has changed.

To change the length of the effect, use the grid options `cellFlashDuration` and `cellFadeDuration`.

By default, value changes caused by updates to column filters are not highlighted with cell flashing. This behaviour can be toggled by enabling the grid option `allowShowChangeAfterFilter`.

### Flash Cells using the API

Alternatively flash cells using the grid API `flashCells(params)`. The params object takes a list of columns and rows to flash, together with the `flashDuration` and the `fadeDuration` values.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `flashCells` | `Function` |  |  | Flash rows, columns or individual cells. Module: [`HighlightChangesModule`](https://www.ag-grid.com/angular-data-grid/modules/). |

When calling `flashCells()`, pass the `flashDuration` and `fadeDuration` values (in milliseconds) as params to change the duration of cell flashing.

#### Flashing Data Changes

```ts
import { Component } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
import "./styles.css";
import {
  CellStyleModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  HighlightChangesModule,
  ModuleRegistry,
  RowApiModule,
  enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  HighlightChangesModule,
  RowApiModule,
  CellStyleModule,
  ClientSideRowModelModule,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div style="height: 100%; display: flex; flex-direction: column">
    <div style="margin-bottom: 4px">
      <button (click)="onFlashOneCell()" style="margin-left: 15px">
        Flash One Cell
      </button>
      <button (click)="onFlashTwoRows()">Flash Two Rows</button>
      <button (click)="onFlashTwoColumns()">Flash Two Columns</button>
    </div>
    <div style="flex-grow: 1">
      <ag-grid-angular
        style="width: 100%; height: 100%;"
        [columnDefs]="columnDefs"
        [defaultColDef]="defaultColDef"
        [rowData]="rowData"
        (gridReady)="onGridReady($event)"
      />
    </div>
  </div> `,
})
export class AppComponent {
  private gridApi!: GridApi;

  columnDefs: ColDef[] = [
    { field: "a" },
    { field: "b" },
    { field: "c" },
    { field: "d" },
    { field: "e" },
    { field: "f" },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    cellClass: "align-right",
    valueFormatter: (params) => {
      return formatNumber(params.value);
    },
  };
  rowData: any[] | null = createRowData();

  onFlashOneCell() {
    // pick fourth row at random
    const rowNode = this.gridApi.getDisplayedRowAtIndex(4)!;
    // pick 'c' column
    this.gridApi.flashCells({ rowNodes: [rowNode], columns: ["c"] });
  }

  onFlashTwoColumns() {
    // flash whole column, so leave row selection out
    this.gridApi.flashCells({ columns: ["c", "d"] });
  }

  onFlashTwoRows() {
    // pick fourth and fifth row at random
    const rowNode1 = this.gridApi.getDisplayedRowAtIndex(4)!;
    const rowNode2 = this.gridApi.getDisplayedRowAtIndex(5)!;
    // flash whole row, so leave column selection out
    this.gridApi.flashCells({ rowNodes: [rowNode1, rowNode2] });
  }

  onGridReady(params: GridReadyEvent) {
    this.gridApi = params.api;
  }
}

function formatNumber(number: number) {
  return Math.floor(number).toLocaleString();
}
function createRowData() {
  const rowData = [];
  for (let i = 0; i < 20; i++) {
    rowData.push({
      a: Math.floor(((i + 323) * 25435) % 10000),
      b: Math.floor(((i + 323) * 23221) % 10000),
      c: Math.floor(((i + 323) * 468276) % 10000),
      d: 0,
      e: 0,
      f: 0,
    });
  }
  return rowData;
}
```

[Live example: Flashing Data Changes](https://www.ag-grid.com/examples/change-cell-renderers/flashing-data-changes/angular)

In the example above, all three buttons use the `flashCells(params)` API. Note the following:

- Clicking **Flash One Cell** uses parameters with one column and one row to flash the intersecting cell.
- Clicking **Flash Two Rows** uses parameters consisting of two row nodes, causing those rows to flash.
- Clicking **Flash Two Columns** uses parameters consisting of two columns, causing those columns to flash.

### Customise Flash Colour

Each time the cell value is changed, the grid adds the CSS class `ag-cell-data-changed` for 500ms by default, and then the CSS class `ag-cell-data-changed-animation` for 1,000ms by default. The grid-provided themes use this to apply a background colour. To override the flash background colour, override the relevant CSS class.

#### Customising Flashing

```ts
import { Component } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
import "./style.css";
import {
  CellStyleModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  HighlightChangesModule,
  ModuleRegistry,
  RowApiModule,
  enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  RowApiModule,
  HighlightChangesModule,
  CellStyleModule,
  ClientSideRowModelModule,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div style="height: 100%; display: flex; flex-direction: column">
    <div style="margin-bottom: 4px">
      <button (click)="onUpdateSomeValues()">Update Some Data</button>
    </div>
    <div style="flex-grow: 1">
      <ag-grid-angular
        style="width: 100%; height: 100%;"
        [columnDefs]="columnDefs"
        [defaultColDef]="defaultColDef"
        [rowData]="rowData"
        (gridReady)="onGridReady($event)"
      />
    </div>
  </div> `,
})
export class AppComponent {
  private gridApi!: GridApi;

  columnDefs: ColDef[] = [
    { field: "a" },
    { field: "b" },
    { field: "c" },
    { field: "d" },
    { field: "e" },
    { field: "f" },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    cellClass: "align-right",
    enableCellChangeFlash: true,
    valueFormatter: (params) => {
      return formatNumber(params.value);
    },
  };
  rowData: any[] | null = createRowData();

  onUpdateSomeValues() {
    const rowCount = this.gridApi.getDisplayedRowCount();
    // pick 20 cells at random to update
    for (let i = 0; i < 20; i++) {
      const row = Math.floor(window.agRandom() * rowCount);
      const rowNode = this.gridApi.getDisplayedRowAtIndex(row)!;
      const col = ["a", "b", "c", "d", "e", "f"][i % 6];
      rowNode.setDataValue(col, Math.floor(window.agRandom() * 10000));
    }
  }

  onGridReady(params: GridReadyEvent) {
    this.gridApi = params.api;
  }
}

function formatNumber(number: number) {
  return Math.floor(number).toLocaleString();
}
function createRowData() {
  const rowData = [];
  for (let i = 0; i < 20; i++) {
    rowData.push({
      a: Math.floor(((i + 323) * 25435) % 10000),
      b: Math.floor(((i + 323) * 23221) % 10000),
      c: Math.floor(((i + 323) * 468276) % 10000),
      d: 0,
      e: 0,
      f: 0,
    });
  }
  return rowData;
}
```

[Live example: Customising Flashing](https://www.ag-grid.com/examples/change-cell-renderers/customising-flashing/angular)

The example above demonstrates customising the flashing cell background colour using the `--ag-value-change-value-highlight-background-color` CSS variable.

## Animated Cell Renderers

Interesting animations for data changes can be achieved using [Cell Components](https://www.ag-grid.com/angular-data-grid/component-cell-renderer/). You can create your own or use one of the provided Show Change Cell Components. The grid provides two such components out of the box.

### Animate Show Changed Cells

The difference between the previous and new value is temporarily shown beside the new value and is then faded out. This difference is shown in either green or red, for an increase or decrease in value respectively, alongside an arrow indicating the direction of change.

#### Animate Show Change Renderer

```ts
import { Component } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
import "./styles.css";
import {
  CellStyleModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  HighlightChangesModule,
  ModuleRegistry,
  RowApiModule,
  TextEditorModule,
  ValueParserParams,
  enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  TextEditorModule,
  RowApiModule,
  CellStyleModule,
  ClientSideRowModelModule,
  HighlightChangesModule,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div class="example-wrapper">
    <div style="margin-bottom: 5px">
      <button (click)="onUpdateSomeValues()">
        Update Some C &amp; D Values
      </button>
    </div>
    <ag-grid-angular
      style="width: 100%; height: 100%;"
      [columnDefs]="columnDefs"
      [defaultColDef]="defaultColDef"
      [rowData]="rowData"
      (gridReady)="onGridReady($event)"
    />
  </div> `,
})
export class AppComponent {
  private gridApi!: GridApi;

  columnDefs: ColDef[] = [
    {
      headerName: "Editable A",
      field: "a",
      editable: true,
      valueParser: numberValueParser,
    },
    {
      headerName: "Editable B",
      field: "b",
      editable: true,
      valueParser: numberValueParser,
    },
    {
      headerName: "API C",
      field: "c",
      minWidth: 135,
      valueParser: numberValueParser,
      cellRenderer: "agAnimateShowChangeCellRenderer",
    },
    {
      headerName: "API D",
      field: "d",
      minWidth: 135,
      valueParser: numberValueParser,
      cellRenderer: "agAnimateShowChangeCellRenderer",
    },
    {
      headerName: "Total",
      valueGetter: "data.a + data.b + data.c + data.d",
      minWidth: 135,
      cellRenderer: "agAnimateShowChangeCellRenderer",
    },
    {
      headerName: "Average",
      valueGetter: "(data.a + data.b + data.c + data.d) / 4",
      minWidth: 135,
      cellRenderer: "agAnimateShowChangeCellRenderer",
    },
  ];
  defaultColDef: ColDef = {
    minWidth: 105,
    flex: 1,
    cellClass: "align-right",
    valueFormatter: (params) => {
      return formatNumber(params.value);
    },
  };
  rowData: any[] | null = createRowData();

  onUpdateSomeValues() {
    const rowCount = this.gridApi.getDisplayedRowCount();
    for (let i = 0; i < 10; i++) {
      const row = Math.floor(window.agRandom() * rowCount);
      const rowNode = this.gridApi.getDisplayedRowAtIndex(row)!;
      rowNode.setDataValue("c", Math.floor(window.agRandom() * 10000));
      rowNode.setDataValue("d", Math.floor(window.agRandom() * 10000));
    }
  }

  onGridReady(params: GridReadyEvent) {
    this.gridApi = params.api;
  }
}

function numberValueParser(params: ValueParserParams) {
  return Number(params.newValue);
}
function formatNumber(number: number) {
  return Math.floor(number).toLocaleString();
}
function createRowData() {
  const rowData = [];
  for (let i = 0; i < 20; i++) {
    rowData.push({
      a: Math.floor(((i + 323) * 25435) % 10000),
      b: Math.floor(((i + 323) * 23221) % 10000),
      c: Math.floor(((i + 323) * 468276) % 10000),
      d: 0,
    });
  }
  return rowData;
}
```

[Live example: Animate Show Change Renderer](https://www.ag-grid.com/examples/change-cell-renderers/animate-show-change-renderer/angular)

The example above demonstrates the following:

- Columns A, B are editable.
- Columns C and D are updated via clicking the button.
- Changes to any of the first 4 columns results in animations in the Total and Average column.
- This can be set as a cell renderer in the column definitions:

```ts
<ag-grid-angular
    [columnDefs]="columnDefs"
    /* other grid options ... */ />

this.columnDefs = [
    // set the cell renderer in the column definition
    { cellRenderer: "agAnimateShowChangeCellRenderer" },
];
```

### Animate Slide Cells

The previous value is shown in a faded fashion and slides, giving a ghosting effect as the old value fades and slides away.

#### Animate Slide Renderer

```ts
import { Component } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
import "./styles.css";
import {
  CellStyleModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  HighlightChangesModule,
  ModuleRegistry,
  RowApiModule,
  TextEditorModule,
  ValueParserParams,
  enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  TextEditorModule,
  RowApiModule,
  CellStyleModule,
  ClientSideRowModelModule,
  HighlightChangesModule,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div class="example-wrapper">
    <div style="margin-bottom: 5px">
      <button (click)="onUpdateSomeValues()">
        Update Some C &amp; D Values
      </button>
    </div>
    <ag-grid-angular
      style="width: 100%; height: 100%;"
      [columnDefs]="columnDefs"
      [defaultColDef]="defaultColDef"
      [rowData]="rowData"
      (gridReady)="onGridReady($event)"
    />
  </div> `,
})
export class AppComponent {
  private gridApi!: GridApi;

  columnDefs: ColDef[] = [
    {
      headerName: "Editable A",
      field: "a",
      editable: true,
      valueParser: numberValueParser,
    },
    {
      headerName: "Editable B",
      field: "b",
      editable: true,
      valueParser: numberValueParser,
    },
    {
      headerName: "API C",
      field: "c",
      minWidth: 135,
      valueParser: numberValueParser,
      cellRenderer: "agAnimateSlideCellRenderer",
    },
    {
      headerName: "API D",
      field: "d",
      minWidth: 135,
      valueParser: numberValueParser,
      cellRenderer: "agAnimateSlideCellRenderer",
    },
    {
      headerName: "Total",
      valueGetter: "data.a + data.b + data.c + data.d",
      minWidth: 135,
      cellRenderer: "agAnimateSlideCellRenderer",
    },
    {
      headerName: "Average",
      valueGetter: "(data.a + data.b + data.c + data.d) / 4",
      minWidth: 135,
      cellRenderer: "agAnimateSlideCellRenderer",
    },
  ];
  defaultColDef: ColDef = {
    minWidth: 105,
    flex: 1,
    cellClass: "align-right",
    valueFormatter: (params) => {
      return formatNumber(params.value);
    },
  };
  rowData: any[] | null = createRowData();

  onUpdateSomeValues() {
    const rowCount = this.gridApi.getDisplayedRowCount();
    for (let i = 0; i < 10; i++) {
      const row = Math.floor(window.agRandom() * rowCount);
      const rowNode = this.gridApi.getDisplayedRowAtIndex(row)!;
      rowNode.setDataValue("c", Math.floor(window.agRandom() * 10000));
      rowNode.setDataValue("d", Math.floor(window.agRandom() * 10000));
    }
  }

  onGridReady(params: GridReadyEvent) {
    this.gridApi = params.api;
  }
}

function numberValueParser(params: ValueParserParams) {
  return Number(params.newValue);
}
function formatNumber(number: number) {
  return Math.floor(number).toLocaleString();
}
function createRowData() {
  const rowData = [];
  for (let i = 0; i < 20; i++) {
    rowData.push({
      a: Math.floor(((i + 323) * 25435) % 10000),
      b: Math.floor(((i + 323) * 23221) % 10000),
      c: Math.floor(((i + 323) * 468276) % 10000),
      d: 0,
    });
  }
  return rowData;
}
```

[Live example: Animate Slide Renderer](https://www.ag-grid.com/examples/change-cell-renderers/animate-slide-renderer/angular)

The example above demonstrates the following:

- Columns A, B are editable.
- Columns C and D are updated via clicking the button.
- Changes to any of the first 4 columns results in animations in the Total and Average column.
- This can be set as a cell renderer in the column definitions:

```ts
<ag-grid-angular
    [columnDefs]="columnDefs"
    /* other grid options ... */ />

this.columnDefs = [
    // set the cell renderer in the column definition
    { cellRenderer: "agAnimateSlideCellRenderer" },
];
```
