Skip to main content
AG Grid provides native Vue 3 support with Composition API, full TypeScript typing, and reactive data binding.

Installation

1

Install the packages

Install AG Grid Vue along with the core library:
npm install ag-grid-vue3 ag-grid-community
For enterprise features:
npm install ag-grid-vue3 ag-grid-community ag-grid-enterprise
2

Import the component

<script setup lang="ts">
import { AgGridVue } from 'ag-grid-vue3';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-quartz.css';
</script>

Basic Usage

<script setup lang="ts">
import { ref } from 'vue';
import { AgGridVue } from 'ag-grid-vue3';
import { ColDef } from 'ag-grid-community';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-quartz.css';

interface IRow {
  make: string;
  model: string;
  price: number;
}

const rowData = ref<IRow[]>([
  { make: 'Tesla', model: 'Model Y', price: 64950 },
  { make: 'Ford', model: 'F-Series', price: 33850 },
  { make: 'Toyota', model: 'Corolla', price: 29600 },
]);

const columnDefs = ref<ColDef<IRow>[]>([
  { field: 'make' },
  { field: 'model' },
  { field: 'price' }
]);
</script>

<template>
  <ag-grid-vue
    class="ag-theme-quartz"
    style="height: 500px"
    :rowData="rowData"
    :columnDefs="columnDefs"
  />
</template>

TypeScript Support

The AgGridVue component provides full TypeScript support with generic types.

Component Props Interface

import { GridOptions, Module } from 'ag-grid-community';

interface Props<TData> {
  /** Initial grid configuration */
  gridOptions?: GridOptions<TData>;
  
  /** Register AG Grid modules for this instance */
  modules?: Module[];
  
  /** All GridOptions properties as individual props */
  // Plus all grid options like:
  rowData?: TData[];
  columnDefs?: ColDef<TData>[];
  // ... and 200+ more options
}

Type-Safe Column Definitions

<script setup lang="ts">
import { ref } from 'vue';
import { ColDef } from 'ag-grid-community';

interface UserData {
  id: number;
  name: string;
  email: string;
  age: number;
}

const columnDefs = ref<ColDef<UserData>[]>([
  { 
    field: 'name',
    headerName: 'Full Name',
    valueGetter: (params) => {
      // params.data is typed as UserData
      return params.data?.name.toUpperCase();
    }
  },
  { field: 'email' },
  { 
    field: 'age',
    filter: 'agNumberColumnFilter',
    cellStyle: (params) => {
      // Type-safe access to row data
      return params.data.age < 18 ? { color: 'red' } : {};
    }
  }
]);
</script>

Accessing the Grid API

Access the Grid API using template refs.
<script setup lang="ts">
import { ref } from 'vue';
import { AgGridVue } from 'ag-grid-vue3';

const gridRef = ref<InstanceType<typeof AgGridVue>>();

const onExportClick = () => {
  gridRef.value?.api.exportDataAsCsv();
};

const onSelectAll = () => {
  gridRef.value?.api.selectAll();
};
</script>

<template>
  <button @click="onExportClick">Export CSV</button>
  <button @click="onSelectAll">Select All</button>
  <ag-grid-vue
    ref="gridRef"
    class="ag-theme-quartz"
    style="height: 500px"
    :rowData="rowData"
    :columnDefs="columnDefs"
  />
</template>
The Grid API is available after the grid-ready event fires.

Event Handling

Bind to grid events using Vue’s event binding syntax with kebab-case.
<script setup lang="ts">
import { 
  CellClickedEvent, 
  RowSelectedEvent,
  GridReadyEvent 
} from 'ag-grid-community';

const onCellClicked = (event: CellClickedEvent) => {
  console.log('Cell clicked:', event.value);
};

const onRowSelected = (event: RowSelectedEvent) => {
  console.log('Row selected:', event.node.data);
};

const onGridReady = (event: GridReadyEvent) => {
  console.log('Grid is ready');
  event.api.sizeColumnsToFit();
};
</script>

<template>
  <ag-grid-vue
    :rowData="rowData"
    :columnDefs="columnDefs"
    rowSelection="multiple"
    @cell-clicked="onCellClicked"
    @row-selected="onRowSelected"
    @grid-ready="onGridReady"
  />
</template>
Event names use kebab-case in templates: @grid-ready, @cell-clicked, @row-selected

Custom Vue Components

Use Vue components as cell renderers, editors, and filters.
<!-- StatusRenderer.vue -->
<script setup lang="ts">
import { computed } from 'vue';

interface Props {
  value: string;
}

const props = defineProps<Props>();

const color = computed(() => {
  return props.value === 'active' ? 'green' : 'red';
});
</script>

<template>
  <span :style="{ color, fontWeight: 'bold' }">
    {{ value }}
  </span>
</template>

Using Custom Components

<script setup lang="ts">
import { ref } from 'vue';
import { ColDef } from 'ag-grid-community';
import StatusRenderer from './StatusRenderer.vue';
import RatingEditor from './RatingEditor.vue';
import YearFilter from './YearFilter.vue';

const columnDefs = ref<ColDef[]>([
  { 
    field: 'status',
    cellRenderer: StatusRenderer
  },
  { 
    field: 'rating',
    cellEditor: RatingEditor,
    editable: true
  },
  { 
    field: 'year',
    filter: YearFilter,
    floatingFilter: true
  }
]);
</script>

Reactive Data Binding

Vue’s reactivity system works seamlessly with AG Grid.
<script setup lang="ts">
import { ref } from 'vue';

const rowData = ref([
  { make: 'Tesla', model: 'Model Y', price: 64950 },
  { make: 'Ford', model: 'F-Series', price: 33850 },
]);

const addRow = () => {
  rowData.value = [
    ...rowData.value,
    { make: 'Toyota', model: 'Corolla', price: 29600 }
  ];
};
</script>

<template>
  <button @click="addRow">Add Row</button>
  <ag-grid-vue
    :rowData="rowData"
    :columnDefs="columnDefs"
  />
</template>

State Management

Integrate with Pinia or Vuex for state management.
// stores/grid.ts
import { defineStore } from 'pinia';

export const useGridStore = defineStore('grid', {
  state: () => ({
    rowData: [],
    loading: false
  }),
  actions: {
    async fetchData() {
      this.loading = true;
      const response = await fetch('/api/data');
      this.rowData = await response.json();
      this.loading = false;
    }
  }
});
<script setup lang="ts">
import { onMounted } from 'vue';
import { useGridStore } from './stores/grid';

const gridStore = useGridStore();

onMounted(() => {
  gridStore.fetchData();
});
</script>

<template>
  <ag-grid-vue
    :rowData="gridStore.rowData"
    :columnDefs="columnDefs"
    :loading="gridStore.loading"
  />
</template>

Props Reference

The AgGridVue component accepts all GridOptions as props:
rowData
TData[]
The data to display in grid rows
columnDefs
ColDef<TData>[]
Column definitions for the grid
gridOptions
GridOptions<TData>
Initial grid configuration (component props take precedence)
modules
Module[]
AG Grid modules to register for this instance
v-model
TData[]
Two-way binding for row data (automatically syncs changes)

Module Registration

// main.ts
import { createApp } from 'vue';
import { ModuleRegistry } from 'ag-grid-community';
import { ClientSideRowModelModule } from 'ag-grid-community';
import { MenuModule } from 'ag-grid-enterprise';

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  MenuModule
]);

createApp(App).mount('#app');

Common Patterns

Dynamic Column Visibility

<script setup lang="ts">
import { ref, computed } from 'vue';

const showPrice = ref(true);

const columnDefs = computed(() => [
  { field: 'make' },
  { field: 'model' },
  ...(showPrice.value ? [{ field: 'price' }] : [])
]);
</script>

<template>
  <label>
    <input type="checkbox" v-model="showPrice" />
    Show Price
  </label>
  <ag-grid-vue
    :rowData="rowData"
    :columnDefs="columnDefs"
  />
</template>

Async Data Loading

<script setup lang="ts">
import { ref, onMounted } from 'vue';

const rowData = ref([]);
const loading = ref(true);

onMounted(async () => {
  loading.value = true;
  const response = await fetch('/api/data');
  rowData.value = await response.json();
  loading.value = false;
});
</script>

<template>
  <ag-grid-vue
    :rowData="rowData"
    :columnDefs="columnDefs"
    :loading="loading"
  />
</template>

Troubleshooting

Make sure you’ve imported the CSS files:
<script setup>
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-quartz.css';
</script>
Set explicit height on the grid:
<template>
  <ag-grid-vue
    class="ag-theme-quartz"
    style="height: 500px"
  />
</template>
Ensure your custom components use defineExpose to expose required methods:
<script setup>
defineExpose({
  getValue: () => value.value,
  // Other required methods
});
</script>
Use immutable updates for reactive data:
// Wrong: Mutates array
rowData.value.push(newRow);

// Correct: Creates new array
rowData.value = [...rowData.value, newRow];

Next Steps

Column Definitions

Configure grid columns

Grid API

Explore API methods

Custom Components

Build Vue components for cells

Styling

Customize appearance