---
title: "SSRM - Single Row Updates"
enterprise: true
framework: javascript
version: "36.1.0"
---

# SSRM - Single Row Updates

This section demonstrates updating rows directly while using the Server-Side Row Model (SSRM).

## Updating Rows API

You can update a single row by using the row node `updateData` or `setData` functions.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `updateData` | `Function` |  |  | Updates the data on the `rowNode`. When this method is called, the grid refreshes the entire rendered row if it is displayed. |
| `setData` | `Function` |  |  | Replaces the data on the `rowNode`. When this method is called, the grid refreshes the entire rendered row if it is displayed. |

> **Note**
>
> Setting row data will NOT change the row node ID, so if you are using `getRowId()` and the data changes such that the ID will be different, the `rowNode` will not have its ID updated.

## Updating Rows Example

The example below demonstrates a basic example, using the API's `forEachNode` function to iterate over all loaded nodes, and updating their version.

- **Set Data:** Sets the row data using `setData` and the grid refreshes the row, notably the cells won't flash with `enableCellChangeFlash`.
- **Update Data:** Updates the row data using `updateData` and the grid refreshes the row, notably the cells do flash with `enableCellChangeFlash`.

#### Updating All Rows

```ts
import {
  ColDef,
  GridApi,
  GridOptions,
  HighlightChangesModule,
  IServerSideDatasource,
  ModuleRegistry,
  RowApiModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  RowGroupingModule,
  ServerSideRowModelModule,
} from "ag-grid-enterprise";
import { FakeServer } from "./fakeServer";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  RowApiModule,
  HighlightChangesModule,
  RowGroupingModule,
  ServerSideRowModelModule,
]);

let versionCounter: number = 0;
const columnDefs: ColDef[] = [
  { field: "athlete" },
  { field: "date" },
  { field: "country" },
  { field: "version" },
];

let gridApi: GridApi;

const gridOptions: GridOptions = {
  defaultColDef: {
    flex: 1,
    sortable: false,
    enableCellChangeFlash: true,
  },
  columnDefs: columnDefs,
  // use the enterprise row model
  rowModelType: "serverSide",
  cacheBlockSize: 75,
};

function setRows() {
  versionCounter += 1;
  const version =
    versionCounter + " - " + versionCounter + " - " + versionCounter;
  gridApi!.forEachNode((node) => {
    node.setData({ ...node.data, version });
  });
}

function updateRows() {
  versionCounter += 1;
  const version =
    versionCounter + " - " + versionCounter + " - " + versionCounter;
  gridApi!.forEachNode((node) => {
    node.updateData({ ...node.data, version });
  });
}

const getServerSideDatasource = (server: any): IServerSideDatasource => {
  return {
    getRows: (params) => {
      console.log("[Datasource] - rows requested by grid: ", params.request);

      const response = server.getData(params.request);

      const dataWithVersion = response.rows.map((rowData: any) => {
        return {
          ...rowData,
          version:
            versionCounter + " - " + versionCounter + " - " + versionCounter,
        };
      });

      // adding delay to simulate real server call
      setTimeout(() => {
        if (response.success) {
          // call the success callback
          params.success({
            rowData: dataWithVersion,
            rowCount: response.lastRow,
          });
        } else {
          // inform the grid request failed
          params.fail();
        }
      }, 1000);
    },
  };
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then(function (data) {
    // setup the fake server with entire dataset
    const fakeServer = new FakeServer(data);

    // create datasource with a reference to the fake server
    const datasource = getServerSideDatasource(fakeServer);

    // register the datasource with the grid
    gridApi!.setGridOption("serverSideDatasource", datasource);
  });

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).setRows = setRows;
  (<any>window).updateRows = updateRows;
}
```

[Live example: Updating All Rows](https://www.ag-grid.com/examples/server-side-model-updating-single-row/updating-all-rows/typescript/)

## Specific Row Updates

The following code snippet outlines the general approach of iterating through all loaded row nodes and then updating target rows with `rowNode.updateData(data)`:

```js
api.forEachNode(rowNode => {
    if (idsToUpdate.indexOf(rowNode.data.id) >= 0) {
        // arbitrarily update some data
        const updated = rowNode.data;
        updated.gold += 1;

        // directly update data in rowNode
        rowNode.updateData(updated);
    }
});
```

The example below demonstrates this snippet in action;

#### Updating Specific Rows

```ts
import {
  ColDef,
  GridApi,
  GridOptions,
  HighlightChangesModule,
  IServerSideDatasource,
  ModuleRegistry,
  RowApiModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  RowGroupingModule,
  ServerSideRowModelModule,
} from "ag-grid-enterprise";
import { FakeServer } from "./fakeServer";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  RowApiModule,
  HighlightChangesModule,
  RowGroupingModule,
  ServerSideRowModelModule,
]);

let versionCounter: number = 0;
const columnDefs: ColDef[] = [
  { field: "athlete" },
  { field: "date" },
  { field: "country" },
  { field: "version" },
];

let gridApi: GridApi;

const gridOptions: GridOptions = {
  defaultColDef: {
    flex: 1,
    sortable: false,
    enableCellChangeFlash: true,
  },
  columnDefs,
  // use the enterprise row model
  rowModelType: "serverSide",
  cacheBlockSize: 75,
  getRowId: (params) => `${params.data.athlete}-${params.data.date}`,
};

function updateRows(athlete?: string, date?: string) {
  versionCounter += 1;
  gridApi!.forEachNode((rowNode) => {
    if (athlete != null && rowNode.data?.athlete !== athlete) {
      // if the athlete doesn't match, skip this row
      // Or row data is empty as it could be the loading row
      return;
    }

    if (date != null && rowNode.data?.date !== date) {
      return;
    }

    // arbitrarily update some data
    const updated = rowNode.data;
    updated.version =
      versionCounter + " - " + versionCounter + " - " + versionCounter;

    // directly update data in rowNode
    rowNode.updateData(updated);
  });
}

const getServerSideDatasource = (server: any): IServerSideDatasource => {
  return {
    getRows: (params) => {
      console.log("[Datasource] - rows requested by grid: ", params.request);

      const response = server.getData(params.request);

      const dataWithVersion = response.rows.map((rowData: any) => {
        return {
          ...rowData,
          version:
            versionCounter + " - " + versionCounter + " - " + versionCounter,
        };
      });

      // adding delay to simulate real server call
      setTimeout(() => {
        if (response.success) {
          // call the success callback
          params.success({
            rowData: dataWithVersion,
            rowCount: response.lastRow,
          });
        } else {
          // inform the grid request failed
          params.fail();
        }
      }, 1000);
    },
  };
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then(function (data) {
    // setup the fake server with entire dataset
    const fakeServer = new FakeServer(data);

    // create datasource with a reference to the fake server
    const datasource = getServerSideDatasource(fakeServer);

    // register the datasource with the grid
    gridApi!.setGridOption("serverSideDatasource", datasource);
  });

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).updateRows = updateRows;
}
```

[Live example: Updating Specific Rows](https://www.ag-grid.com/examples/server-side-model-updating-single-row/updating-specific-rows/typescript/)

## Selected Row Updates

The example below demonstrates how to update all of the rows which the user has selected, note the following:

- The **Update Selected Rows** button will update the row version directly on the selected row nodes.
- The selected nodes are obtained using `api.getSelectedNodes()`, and are then individually updated.

#### Updating Selected Rows

```ts
import {
  ColDef,
  GridApi,
  GridOptions,
  HighlightChangesModule,
  IServerSideDatasource,
  ModuleRegistry,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import {
  RowGroupingModule,
  ServerSideRowModelModule,
} from "ag-grid-enterprise";
import { FakeServer } from "./fakeServer";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  HighlightChangesModule,
  RowGroupingModule,
  ServerSideRowModelModule,
]);

let versionCounter: number = 0;
const columnDefs: ColDef[] = [
  { field: "athlete" },
  { field: "country" },
  { field: "date" },
  { field: "version" },
];

let gridApi: GridApi;

const gridOptions: GridOptions = {
  defaultColDef: {
    flex: 1,
    sortable: false,
    enableCellChangeFlash: true,
  },
  columnDefs: columnDefs,
  rowSelection: { mode: "multiRow", headerCheckbox: false },
  // use the enterprise row model
  rowModelType: "serverSide",
  cacheBlockSize: 75,
  getRowId: (params) => `${params.data.athlete}-${params.data.date}`,
};

const getServerSideDatasource = (server: any): IServerSideDatasource => {
  return {
    getRows: (params) => {
      console.log("[Datasource] - rows requested by grid: ", params.request);

      const response = server.getData(params.request);

      const dataWithVersion = response.rows.map((rowData: any) => {
        return {
          ...rowData,
          version:
            versionCounter + " - " + versionCounter + " - " + versionCounter,
        };
      });

      // adding delay to simulate real server call
      setTimeout(() => {
        if (response.success) {
          // call the success callback
          params.success({
            rowData: dataWithVersion,
            rowCount: response.lastRow,
          });
        } else {
          // inform the grid request failed
          params.fail();
        }
      }, 1000);
    },
  };
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then(function (data) {
    // setup the fake server with entire dataset
    const fakeServer = new FakeServer(data);

    // create datasource with a reference to the fake server
    const datasource = getServerSideDatasource(fakeServer);

    // register the datasource with the grid
    gridApi!.setGridOption("serverSideDatasource", datasource);
  });

function updateSelectedRows() {
  versionCounter += 1;
  const version =
    versionCounter + " - " + versionCounter + " - " + versionCounter;
  const nodesToUpdate = gridApi!.getSelectedNodes();
  nodesToUpdate.forEach((node) => {
    node.updateData({ ...node.data, version });
  });
}

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).updateSelectedRows = updateSelectedRows;
}
```

[Live example: Updating Selected Rows](https://www.ag-grid.com/examples/server-side-model-updating-single-row/updating-selected-row/typescript/)
