---
product: "AG Grid"
title: "Cell Components"
description: "Component cell renderers allow images, buttons, and hyperlinks to be added to Vue Table Cells. Use a provided cell renderer or create a custom cell renderer."
framework: vue
version: "36.2.0"
related:
    - title: "Getting Values"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/value-getters/"
    - title: "Text Formatting"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/value-formatters/"
    - title: "Cell Data Types"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/cell-data-types/"
llms: "https://www.ag-grid.com/archive/36.2.0/llms.txt"
---

# Cell Components

Custom HTML / DOM inside Cells is achieved using Cell Components. Create Custom Cell Components to have any HTML markup in a cell. The grid comes with some Provided Cell Components for common grid tasks.

The example below shows adding images, hyperlinks, and buttons to a cell using Custom Cell Components. The custom button logs to the developer console when clicked.

#### Simple Cell Renderer

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  CellStyleModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import CompanyLogoRenderer from "./companyLogoRendererVue";
import CompanyRenderer from "./companyRendererVue";
import CustomButtonComponent from "./customButtonComponentVue";
import MissionResultRenderer from "./missionResultRendererVue";
import PriceRenderer from "./priceRendererVue";

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

ModuleRegistry.registerModules([CellStyleModule, ClientSideRowModelModule]);

interface IRow {
  company: string;
  website: string;
  revenue: number;
  hardware: boolean;
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :defaultColDef="defaultColDef"
      :columnDefs="columnDefs"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    CompanyLogoRenderer,
    CompanyRenderer,
    CustomButtonComponent,
    MissionResultRenderer,
    PriceRenderer,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IRow> | null>(null);
    const defaultColDef = ref<ColDef>({
      flex: 10,
    });
    const columnDefs = ref<ColDef[]>([
      {
        field: "company",
        flex: 6,
      },
      {
        field: "website",
        cellRenderer: "CompanyRenderer",
      },
      {
        headerName: "Logo",
        field: "company",
        cellRenderer: "CompanyLogoRenderer",
        cellClass: "logoCell",
        minWidth: 100,
      },
      {
        field: "revenue",
        cellRenderer: "PriceRenderer",
        flex: 8,
      },
      {
        field: "hardware",
        cellRenderer: "MissionResultRenderer",
        flex: 8,
      },
      {
        colId: "actions",
        headerName: "Actions",
        cellRenderer: "CustomButtonComponent",
        minWidth: 160,
      },
    ]);
    const rowData = ref<IRow[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        rowData.value = data;
      };

      fetch("https://www.ag-grid.com/example-assets/small-company-data.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      defaultColDef,
      columnDefs,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Simple Cell Renderer](https://www.ag-grid.com/archive/36.2.0/examples/component-cell-renderer/cell-renderer-summary/vue3/)

## Provided Components

The grid comes with some built in Cell Components that cover some common cell rendering requirements.

- [Group Cell Component](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping-single-group-column/#cell-component): For showing group details with expand and collapse functionality when using any of [Row Grouping](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping/), [Master Detail](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/master-detail/) or [Tree Data](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/tree-data/).
- [Animate Change Cell Renderers](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/change-cell-renderers/#animated-cell-renderers): For animating changes when data is updated.
- [Checkbox Cell Renderer](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/cell-data-types/#boolean): For displaying boolean values with a checkbox when `cellDataType` of Boolean is used.

## Custom Components

To render custom content in a grid cell, first define the custom cell component and then configure the column definition to use the component via `cellRenderer` or `cellRendererSelector`, passing custom parameters via `cellRendererParams` as required.

`params.value` passed to a Cell Component may be `null` or `undefined`, e.g. for group rows or rows whose data has not loaded, so custom components must handle this themselves. See [TypeScript Generics](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/typescript-generics/) for how typing `ICellRendererParams<TData, TValue>` surfaces this at compile time.

### Creating Custom Components

A cell renderer is either:

- A function returning an HTML string or a DOM object
- A regular Vue component

Use the function variant of a Cell Component if you have no refresh requirements.

When providing a Vue component, you can access the `params` object via `this.params` in the usual methods (lifecycle hooks, methods etc), and via `props.params` when using `setup`. The full definition of `params` can be found below in the [API Reference](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/component-cell-renderer/#api-reference).

```ts
  // ...
  beforeMount() {
    this.cellValue = this.params.value;
  }
  // ...
```

When providing a function-based component, it receives the same `params` as its argument as would have been provided to the Vue component via `this.params` above. In the example below we're outputting a string value that depends on the cell value:

```js
<template>
    <ag-grid-vue :columnDefs="columnDefs" ...other properties>
    </ag-grid-vue>
</template>

<script>
//...other imports
import {AgGridVue} from "ag-grid-vue3";

export default {
    components: {
        AgGridVue
    },
    data() {
        return {
            columnDefs: [
                {
                    headerName: "Value",
                    field: "value",
                    cellRenderer: params => params.value > 1000 ? "LARGE VALUE" : "SMALL VALUE"
                }
            ]
        }
    }
    //...
}
</script>
```

It is also possible to write a JavaScript-based Cell Component - refer to the [documentation here](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/component-cell-renderer/#creating-custom-components) for more information

### Providing Custom Components

The Cell Component for a Column is set via `colDef.cellRenderer` and can be any of the following types:

1. `String`: The name of a registered Cell Component, see [Registering Custom Components](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/components/#registering-custom-components)
2. `Function`: A function that returns either an HTML string or DOM element for display.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `cellRenderer` | `any` |  |  |  |

The code snippet below demonstrates each of these method types.

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    // 1 - String - The name of a Cell Component registered with the grid.
    {
        field: 'age',
        cellRenderer: 'agGroupCellRenderer',
    },
    // 2 - Function - A function that returns an HTML string or DOM element for display
    {
        field: 'year',
        cellRenderer: params => {
            // put the value in bold
            return 'Value is <b>' + params.value + '</b>';
        }
    }
];
```

### Providing Custom Components Dynamically

The `colDef.cellRendererSelector` function allows setting different Cell Components for different Rows within a Column.

The `params` passed to `cellRendererSelector` are the same as those passed to the [Cell Renderer Component](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/component-cell-renderer/). Typically the selector will use this to check the row's contents and choose a renderer accordingly.

The result is an object with `component` and `params` to use instead of `cellRenderer` and `cellRendererParams`.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `cellRendererSelector` | `CellRendererSelectorFunc` |  |  |  |

This following shows the selector choosing between Mood and Gender Cell Renderers based on the row data.

```js
cellRendererSelector: params => {

    const type = params.data.type;

    if (type === 'gender') {
        return {
            component: 'GenderCellRenderer',
            params: {values: ['Male', 'Female']}
        };
    }

    if (type === 'mood') {
        return {
            component: 'MoodCellRenderer'
        };
    }

    return undefined;
}
```

Another use case for the Selector function is to only render a custom cell component in leaf nodes when [Row Grouping](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping/). This is done by checking `params.node.group` and returning `undefined` for the group nodes.

```js
cellRendererSelector: params => {
    return params.node.group ? undefined : { component: 'CellRenderer' };
},
```

The example below demonstrates the use of `cellRendererSelector` to dynamically select a Cell Component based on the row data.

- The column 'Value' holds data of different types as shown in the column 'Type' (numbers/genders/moods).
- `colDef.cellRendererSelector` is a function that selects the renderer based on the row data.
- The column 'Rendered Value' show the data rendered applying the component and params specified by `colDef.cellRendererSelector`

#### Dynamic Rendering Component

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  CellEditingStartedEvent,
  CellEditingStoppedEvent,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ICellRendererParams,
  ModuleRegistry,
  RowEditingStartedEvent,
  RowEditingStoppedEvent,
  enableDevValidations,
} from "ag-grid-community";
import GenderRenderer from "./genderRendererVue";
import MoodRenderer from "./moodRendererVue";

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

ModuleRegistry.registerModules([ClientSideRowModelModule]);

interface IRow {
  value: number | string;
  type: "age" | "gender" | "mood";
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :rowData="rowData"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    GenderRenderer,
    MoodRenderer,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IRow> | null>(null);
    const rowData = ref<IRow[] | null>([
      { value: 14, type: "age" },
      { value: "Female", type: "gender" },
      { value: "Happy", type: "mood" },
      { value: 21, type: "age" },
      { value: "Male", type: "gender" },
      { value: "Sad", type: "mood" },
    ]);
    const columnDefs = ref<ColDef[]>([
      { field: "value" },
      {
        headerName: "Rendered Value",
        field: "value",
        cellRendererSelector: (params: ICellRendererParams<IRow>) => {
          const moodDetails = {
            component: "MoodRenderer",
          };
          const genderDetails = {
            component: "GenderRenderer",
            params: { values: ["Male", "Female"] },
          };
          if (params.data) {
            if (params.data.type === "gender") return genderDetails;
            else if (params.data.type === "mood") return moodDetails;
          }
          return undefined;
        },
      },
      { field: "type" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      cellDataType: false,
    });

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;
    };

    return {
      gridApi,
      rowData,
      columnDefs,
      defaultColDef,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Dynamic Rendering Component](https://www.ag-grid.com/archive/36.2.0/examples/component-cell-renderer/dynamic-rendering-component/vue3/)

### Custom Props

The `props` passed to the Cell Component can be complemented with custom props. This allows configuring reusable Cell Components - e.g. a component could have buttons that are optionally displayed via additional props.

Complement props to a cell renderer using the Column Definition attribute `cellRendererParams`. When provided, these props will be merged with the grid provided props.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `cellRendererParams` | `any` |  |  |  |

```js
<template>
    <ag-grid-vue :columnDefs="columnDefs" ...other properties>
    </ag-grid-vue>
</template>

<script>
//...other imports
import {AgGridVue} from "ag-grid-vue3";

// define Cell Component to be reused
const ColourComponent = {
  template: '<span :style="{color: params.color}">{{params.value}}</span>'
};

export default {
    components: {
        AgGridVue,
        ColourComponent
    },
    data() {
        return {
            columnDefs: [
                {
                    headerName: "Colour 1",
                    field: "value",
                    cellRenderer: 'ColourComponent',
                    cellRendererParams: {
                        color: 'guinnessBlack'
                    }
                },
                {
                    headerName: "Colour 2",
                    field: "value",
                    cellRenderer: 'ColourComponent',
                    cellRendererParams: {
                        color: 'irishGreen'
                    }
                }
            ]
        }
    }
    //...other properties & methods
}
</script>
```

This example shows rendering an image with and without custom props and using custom props to pass a callback to a button. The `Refresh Data` button triggers the cell components to refresh by randomising the success data. The `Launch` button logs a message to the developer console.

#### Custom Props

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelApiModule,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  RowApiModule,
  enableDevValidations,
} from "ag-grid-community";
import CustomButtonComponent from "./customButtonComponentVue";
import MissionResultRenderer from "./missionResultRendererVue";

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

ModuleRegistry.registerModules([
  RowApiModule,
  ClientSideRowModelModule,
  ClientSideRowModelApiModule,
]);

interface IRow {
  company: string;
  location: string;
  price: number;
  successful: boolean;
}

// Override the icons via cellRendererParams
function successIconSrc(params: boolean) {
  if (params === true) {
    return "https://www.ag-grid.com/example-assets/svg-icons/tick.svg";
  } else {
    return "https://www.ag-grid.com/example-assets/svg-icons/cross.svg";
  }
}

const onClick = () => console.log("Mission Launched");

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div style="margin-bottom: 5px">
        <button v-on:click="refreshData()">Refresh Data</button>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :rowData="rowData"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    CustomButtonComponent,
    MissionResultRenderer,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IRow> | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "company",
      },
      {
        field: "successful",
        headerName: "Success",
        cellRenderer: "MissionResultRenderer",
      },
      {
        field: "successful",
        headerName: "Success (Custom Props)",
        cellRenderer: "MissionResultRenderer",
        cellRendererParams: {
          src: successIconSrc,
        },
      },
      {
        colId: "actions",
        headerName: "Actions",
        cellRenderer: "CustomButtonComponent",
        cellRendererParams: (params: any) => ({
          onClick: onClick,
          params,
        }),
        sortable: false,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
    });
    const rowData = ref<IRow[]>(null);

    function refreshData() {
      gridApi.value.forEachNode((rowNode) => {
        rowNode.setDataValue("successful", window.agRandom() > 0.5);
      });
      gridApi.value.refreshClientSideRowModel("sort");
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        rowData.value = data;
      };

      fetch(
        "https://www.ag-grid.com/example-assets/small-space-mission-data.json",
      )
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      rowData,
      onGridReady,
      refreshData,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Custom Props](https://www.ag-grid.com/archive/36.2.0/examples/component-cell-renderer/custom-props/vue3/)

### Dynamic Tooltips

When working with Custom Cell Renderers it is possible to register custom tooltips that are displayed dynamically by calling the `setTooltip` method on the params passed to the component.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `setTooltip` | `Function` |  |  |  |

The example below demonstrates a dynamic tooltip being displayed on Cell Components. The following can be noted:

- The Athlete column uses the `shouldDisplayTooltip` callback to only display Tooltips when the text is not fully displayed.

#### Dynamic Tooltips

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  TextEditorModule,
  TextFilterModule,
  TooltipModule,
  enableDevValidations,
} from "ag-grid-community";
import AthleteCellRenderer from "./athleteCellRendererVue";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  TextEditorModule,
  TextFilterModule,
  ClientSideRowModelModule,
  TooltipModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    AthleteCellRenderer,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", width: 120, cellRenderer: "AthleteCellRenderer" },
      { field: "country", width: 150 },
    ]);
    const defaultColDef = ref<ColDef>({
      editable: true,
      minWidth: 100,
      filter: true,
    });
    const rowData = ref<IOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        rowData.value = data;
      };

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Dynamic Tooltips](https://www.ag-grid.com/archive/36.2.0/examples/component-cell-renderer/dynamic-tooltips/vue3/)

### Defer Slow Cell Components

If a Custom Cell Component is slow to render, the grid may appear unresponsive due to the custom component blocking the main thread. This can be avoided by deferring the rending of slow components as follows:

```js
{
    cellRenderer: 'SlowCellRenderer',
    cellRendererParams: {
        deferRender: true
    }
}
```

Deferred components will be rendered after other cells and only after the grid has stopped scrolling. In the meantime, the loading cell renderer will be displayed. If [Row Grouping](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/grouping/) is active only custom cells in leaf nodes will be deferred.

The example below demonstrates the use of `deferRender` to defer the rendering of an artificially slow cell component. The following can be noted when scrolling:

- The column 'Slow Renderer' is deferred and shows the default skeleton cell loader.
- The column 'Slow Renderer Custom' is deferred but uses a custom loading cell defined via `colDef.loadingCellRenderer`.
- The column 'Fast Renderer' is a custom component but not deferred so renders immediately along with the other plain cells.
- The `cellRendererSelector` only returns the Slow Cell Renderer for leaf nodes as an optimisation.

#### Slow Cell Renderer

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ICellRendererParams,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import { RowGroupingModule } from "ag-grid-enterprise";
import CustomLoadingCellRenderer from "./customLoadingCellRendererVue";
import FastRenderer from "./fastRendererVue";
import SlowRenderer from "./slowRendererVue";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, RowGroupingModule]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :rowBuffer="rowBuffer"
        :groupDefaultExpanded="groupDefaultExpanded"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :rowData="rowData"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    CustomLoadingCellRenderer,
    FastRenderer,
    SlowRenderer,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const rowBuffer = ref(5);
    const groupDefaultExpanded = ref(1);
    const columnDefs = ref<ColDef[]>([
      {
        field: "athlete",
        rowGroup: true,
        hide: true,
      },
      {
        field: "country",
        headerName: "Slow Renderer",
        cellRendererSelector: (params: ICellRendererParams) => {
          // Optimisation to only use the slow renderer for leaf nodes and not for groups
          return params.node.group ? undefined : { component: "SlowRenderer" };
        },
        cellRendererParams: {
          deferRender: true,
        },
      },
      {
        field: "bronze",
        headerName: "Slow Renderer Custom",
        cellRendererSelector: (params: ICellRendererParams) => {
          // Optimisation to only use the slow renderer for leaf nodes and not for groups
          return params.node.group ? undefined : { component: "SlowRenderer" };
        },
        cellRendererParams: {
          deferRender: true,
        },
        loadingCellRenderer: "CustomLoadingCellRenderer",
      },
      {
        field: "gold",
        headerName: "Fast Renderer",
        cellRenderer: "FastRenderer",
      },
      {
        field: "sport",
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      autoHeaderHeight: true,
      wrapHeaderText: true,
    });
    const rowData = ref<IOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        rowData.value = data;
      };

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      rowBuffer,
      groupDefaultExpanded,
      columnDefs,
      defaultColDef,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Slow Cell Renderer](https://www.ag-grid.com/archive/36.2.0/examples/component-cell-renderer/slow-cell-renderer/vue3/)

### Accessing Instances

After the grid has created an instance of a Cell Component for a cell it is possible to access that instance. This is useful if you want to call a method that you provide on the Cell Component that has nothing to do with the operation of the grid. Accessing Cell Components is done using the grid API `getCellRendererInstances(params)`.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getCellRendererInstances` | `Function` |  |  |  |

An example of getting the Cell Component for exactly one cell is as follows:

```js
// example - get cell renderer for first row and column 'gold'
const firstRowNode = api.getDisplayedRowAtIndex(0);
const params = { columns: ['gold'], rowNodes: [firstRowNode] };
const instances = api.getCellRendererInstances(params);

if (instances.length > 0) {
    // got it, user must be scrolled so that it exists
    const instance = instances[0];
}
```

Note that this method will only return instances of the Cell Component that exists. Due to Row and Column Virtualisation, Cell Components will only exist for Cells that are within the viewport of the Vertical and Horizontal scrolls.

The example below demonstrates custom methods on Cell Components called by the application. The following can be noted:

- The medal columns are all using the user defined `MedalCellRenderer`. The Cell Component has an arbitrary method `medalUserFunction()` which prints some data to the developer console.
- The **Gold** button executes a method on all instances of the Cell Component in the gold column and prints the data to the developer console.
- The **First Row Gold** button executes a method on the gold cell of the first row only and prints data to the developer console. Note that the `getCellRendererInstances()` method will return nothing if the grid is scrolled far past the first row showing row virtualisation in action.
- The **All Cells** button executes a method on all instances of all Cell Components and prints data to the developer console.

#### Get Cell Renderer

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  NumberFilterModule,
  RenderApiModule,
  RowApiModule,
  TextEditorModule,
  TextFilterModule,
  ValueGetterParams,
  enableDevValidations,
} from "ag-grid-community";
import MedalCellRenderer from "./medalCellRendererVue";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  RenderApiModule,
  NumberEditorModule,
  TextEditorModule,
  TextFilterModule,
  NumberFilterModule,
  RowApiModule,
  ClientSideRowModelModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div style="margin-bottom: 5px">
        <button v-on:click="onCallGold()">Gold</button>
        <button v-on:click="onFirstRowGold()">First Row Gold</button>
        <button v-on:click="onCallAllCells()">All Cells</button>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :rowData="rowData"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    MedalCellRenderer,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", width: 150 },
      { field: "country", width: 150 },
      { field: "year", width: 100 },
      { field: "gold", width: 100, cellRenderer: "MedalCellRenderer" },
      { field: "silver", width: 100, cellRenderer: "MedalCellRenderer" },
      { field: "bronze", width: 100, cellRenderer: "MedalCellRenderer" },
      {
        field: "total",
        editable: false,
        valueGetter: (params: ValueGetterParams) =>
          params.data.gold + params.data.silver + params.data.bronze,
        width: 100,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      editable: true,
      flex: 1,
      minWidth: 100,
      filter: true,
    });
    const rowData = ref<IOlympicData[]>(null);

    function onCallGold() {
      console.log("=========> calling all gold");
      // pass in list of columns, here it's gold only
      const params = { columns: ["gold"] };
      const instances = gridApi.value!.getCellRendererInstances(
        params,
      ) as any[];
      instances.forEach((instance) => {
        instance.medalUserFunction();
      });
    }
    function onFirstRowGold() {
      console.log("=========> calling gold row one");
      // pass in one column and one row to identify one cell
      const firstRowNode = gridApi.value!.getDisplayedRowAtIndex(0)!;
      const params = { columns: ["gold"], rowNodes: [firstRowNode] };
      const instances = gridApi.value!.getCellRendererInstances(
        params,
      ) as any[];
      instances.forEach((instance) => {
        instance.medalUserFunction();
      });
    }
    function onCallAllCells() {
      console.log("=========> calling everything");
      // no params, goes through all rows and columns where cell renderer exists
      const instances = gridApi.value!.getCellRendererInstances() as any[];
      instances.forEach((instance) => {
        instance.medalUserFunction();
      });
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        rowData.value = data;
      };

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      rowData,
      onGridReady,
      onCallGold,
      onFirstRowGold,
      onCallAllCells,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Get Cell Renderer](https://www.ag-grid.com/archive/36.2.0/examples/component-cell-renderer/get-cell-renderer/vue3/)

### Keyboard Navigation

When using custom Cell Components, the custom Cell Component is responsible for implementing support for keyboard navigation among its focusable elements. This is why by default, focusing a grid cell with a custom Cell Component will focus the entire cell instead of any of the elements inside the custom cell renderer.

In order to handle focus in your custom cell component, implement [Custom Cell Component Keyboard Navigation](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/keyboard-navigation/#custom-cell-component).

### Handling Mouse Events

By default when a cell is clicked on, the grid will perform actions including:

- Focusing the cell.
- Updating the cell selection, if [Cell Selection](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/cell-selection/) is enabled.
- Selecting the row, if [Row Selection](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/row-selection/) is enabled.
- Starting editing, if [Editing](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/cell-editing/) is enabled.

This behaviour may not be desirable for custom cell components, e.g. if they contain interactive elements. In this situation, the grid can be prevented from handling the mouse event (`'click'`, `'dblclick'`, `'mousedown'` or `'touchstart'`), by passing the `suppressMouseEventHandling` callback to `cellRendererParams`.

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    {
        colId: 'customButton',
        cellRenderer: CustomButtonComponent,
        cellRendererParams: {
            suppressMouseEventHandling: (params) => true,
        },
    },
];
```

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `suppressMouseEventHandling` | `Function` |  |  |  |

Note that whilst the callback will prevent the grid from performing actions, it will still continue to fire events (e.g. `onCellClicked`). These events will have the `isEventHandlingSuppressed` property set to `true` if the callback returns `true`.

The following example demonstrates using `suppressMouseEventHandling` with cell selection, row selection, and editing. Mouse events are suppressed for the Button column.

#### Handling Mouse Events

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  CellClickedEvent,
  CellDoubleClickedEvent,
  CellMouseDownEvent,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  EventCellRendererParams,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  RowClickedEvent,
  RowDoubleClickedEvent,
  RowSelectionModule,
  SuppressMouseEventHandlingParams,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { CellSelectionModule } from "ag-grid-enterprise";
import CustomButtonComponent from "./customButtonComponentVue";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  CellSelectionModule,
  RowSelectionModule,
  TextEditorModule,
  NumberEditorModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div style="margin-bottom: 5px">
        <button id="enableCellSelection" v-on:click="toggleCellSelection()">Enable Cell Selection</button>
        <button id="rowSelection" v-on:click="toggleRowSelection()">Enable Row Selection</button>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :rowData="rowData"
        :defaultColDef="defaultColDef"
        :columnDefs="columnDefs"
        @cell-clicked="onCellClicked"
        @cell-mouse-down="onCellMouseDown"
        @cell-double-clicked="onCellDoubleClicked"
        @row-clicked="onRowClicked"
        @row-double-clicked="onRowDoubleClicked"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    CustomButtonComponent,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const rowData = ref<any[] | null>([
      { id: 1 },
      { id: 2 },
      { id: 3 },
      { id: 4 },
    ]);
    const defaultColDef = ref<ColDef>({
      editable: true,
    });
    const columnDefs = ref<ColDef[]>([
      {
        field: "id",
      },
      {
        colId: "customButton",
        headerName: "Button",
        cellRenderer: "CustomButtonComponent",
        cellRendererParams: {
          suppressMouseEventHandling: (
            params: SuppressMouseEventHandlingParams,
          ) => {
            console.log("suppressMouseEventHandling", params);
            return true;
          },
        } as EventCellRendererParams,
      },
    ]);

    function onCellClicked(e: CellClickedEvent) {
      console.log(
        e.type,
        "isEventHandlingSuppressed",
        e.isEventHandlingSuppressed,
      );
    }
    function onCellMouseDown(e: CellMouseDownEvent) {
      console.log(
        e.type,
        "isEventHandlingSuppressed",
        e.isEventHandlingSuppressed,
      );
    }
    function onCellDoubleClicked(e: CellDoubleClickedEvent) {
      console.log(
        e.type,
        "isEventHandlingSuppressed",
        e.isEventHandlingSuppressed,
      );
    }
    function onRowClicked(e: RowClickedEvent) {
      console.log(
        e.type,
        "isEventHandlingSuppressed",
        e.isEventHandlingSuppressed,
      );
    }
    function onRowDoubleClicked(e: RowDoubleClickedEvent) {
      console.log(
        e.type,
        "isEventHandlingSuppressed",
        e.isEventHandlingSuppressed,
      );
    }
    function toggleCellSelection() {
      const enableCellSelection = !gridApi.value.getGridOption("cellSelection");
      gridApi.value.setGridOption("cellSelection", enableCellSelection);
      document.querySelector("#enableCellSelection")!.textContent =
        enableCellSelection
          ? "Disable Cell Selection"
          : "Enable Cell Selection";
    }
    function toggleRowSelection() {
      const oldRowSelection = gridApi.value.getGridOption("rowSelection");
      gridApi.value.setGridOption(
        "rowSelection",
        oldRowSelection
          ? undefined
          : {
              mode: "multiRow",
              enableClickSelection: true,
            },
      );
      document.querySelector("#rowSelection")!.textContent = !oldRowSelection
        ? "Disable Row Selection"
        : "Enable Row Selection";
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;
    };

    return {
      gridApi,
      rowData,
      defaultColDef,
      columnDefs,
      onGridReady,
      onCellClicked,
      onCellMouseDown,
      onCellDoubleClicked,
      onRowClicked,
      onRowDoubleClicked,
      toggleCellSelection,
      toggleRowSelection,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

[Live example: Handling Mouse Events](https://www.ag-grid.com/archive/36.2.0/examples/component-cell-renderer/handling-mouse-events/vue3/)

It is also possible to stop propagation on mouse events from within a custom cell component, but this must be done for each of the mouse events described above.

### API Reference

Properties available on the `ICellRendererComp&lt;TData = any&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getGui` | `Function` |  |  |  |
| `destroy` | `Function` |  |  |  |
| `init` | `Function` |  |  |  |
| `refresh` | `Function` |  |  |  |

Properties available on the `ICellRendererParams&lt;TData = any, TValue = any, TContext = any&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `value` | `TValue \| null \| undefined` |  |  |  |
| `valueFormatted` | `string \| null \| undefined` |  |  |  |
| `fullWidth` | `boolean` |  |  |  |
| `pinned` | `'left' \| 'right' \| null` |  |  |  |
| `data` | `TData \| undefined` |  |  |  |
| `node` | `IRowNode` |  |  |  |
| `colDef` | `ColDef` |  |  |  |
| `column` | `Column` |  |  |  |
| `eGridCell` | `HTMLElement` |  |  |  |
| `eParentOfValue` | `HTMLElement` |  |  |  |
| `getValue` | `Function` |  |  |  |
| `setValue` | `Function` |  |  |  |
| `formatValue` | `Function` |  |  |  |
| `refreshCell` | `Function` |  |  |  |
| `registerRowDragger` | `Function` |  |  |  |
| `setTooltip` | `Function` |  |  |  |
| `api` | `GridApi` |  |  |  |
| `context` | `TContext` |  |  |  |
