---
product: "AG Grid"
title: "Fill Handle"
description: "When working with cell selection, a Fill Handle allows you to run operations on cells as you adjust the size of the range."
enterprise: true
framework: vue
version: "36.2.0"
related:
    - title: "Range Handle"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/cell-selection-handle/"
    - title: "API Reference"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/cell-selection-api-reference/"
llms: "https://www.ag-grid.com/archive/36.2.0/llms.txt"
---

# Fill Handle

When working with cell selection, a Fill Handle allows you to run operations on cells as you adjust the size of the range.

## Enabling the Fill Handle

To enable the Fill Handle, set `cellSelection.handle` to `{ mode: 'fill' }` in the `gridOptions` as shown below:

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

this.cellSelection = {
    handle: {
        mode: 'fill',
    }
};
```

The example below demonstrates the [default behaviour](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/cell-selection-fill-handle/#default-fill-handle) with the minimal configuration above:

#### Fill Handle

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  CellSelectionOptions,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { CellSelectionModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :cellSelection="cellSelection"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", minWidth: 150 },
      { field: "age", maxWidth: 90 },
      { field: "country", minWidth: 150 },
      { field: "year", maxWidth: 90 },
      { field: "date", minWidth: 150 },
      { field: "sport", minWidth: 150 },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      editable: true,
      cellDataType: false,
    });
    const cellSelection = ref<boolean | CellSelectionOptions>({
      handle: { mode: "fill" },
    });
    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/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

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

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

[Live example: Fill Handle](https://www.ag-grid.com/archive/36.2.0/examples/cell-selection-fill-handle/fill-handle/vue3/)

## Default Fill Handle

The default Fill Handle behaviour will be as close as possible to other spreadsheet applications. Note the following:

### Single Cell

- When a single cell is selected and the range is increased, the value of that cell will be copied to the cells added to the range.
- When a single cell containing a **number** value is selected and the range is increased while pressing the `⌥ Alt` key, that value will be incremented (or decremented if dragging to the left or up) by the value of one until all new cells have been filled.

### Multi Cell

- When a range of numbers is selected and that range is extended, the Grid will detect the linear progression of the selected items and fill the extra cells with calculated values.
- When a range of strings or a mix of strings and numbers are selected and that range is extended, the range items will be copied in order until all new cells have been properly filled.
- When a range of numbers is selected and the range is increased while pressing the `⌥ Alt` key, the behaviour will be the same as when a range of strings or mixed values is selected.

### Range Reduction

- When reducing the size of the range, cells that are no longer part of the range will be cleared (set to `null`). If your column uses a `valueParser`, it will receive an empty string (`''`) as the new value.

#### Fill Handle

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  CellSelectionOptions,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { CellSelectionModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :cellSelection="cellSelection"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", minWidth: 150 },
      { field: "age", maxWidth: 90 },
      { field: "country", minWidth: 150 },
      { field: "year", maxWidth: 90 },
      { field: "date", minWidth: 150 },
      { field: "sport", minWidth: 150 },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      editable: true,
      cellDataType: false,
    });
    const cellSelection = ref<boolean | CellSelectionOptions>({
      handle: { mode: "fill" },
    });
    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/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

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

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

[Live example: Fill Handle](https://www.ag-grid.com/archive/36.2.0/examples/cell-selection-fill-handle/fill-handle/vue3/)

### Suppress Clear On Range Reduction

Reducing a range selection with the Fill Handle will clear cell contents by default, as can be observed in the [cell reduction](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/cell-selection-fill-handle/#range-reduction) example above.

If this behaviour for decreasing selection needs to be prevented, the flag `cellSelection.handle.suppressClearOnFillReduction` should be set to `true`.

#### Fill Handle - Range Reduction

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  CellSelectionOptions,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { CellSelectionModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :cellSelection="cellSelection"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", minWidth: 150 },
      { field: "age", maxWidth: 90 },
      { field: "country", minWidth: 150 },
      { field: "year", maxWidth: 90 },
      { field: "date", minWidth: 150 },
      { field: "sport", minWidth: 150 },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      editable: true,
      cellDataType: false,
    });
    const cellSelection = ref<boolean | CellSelectionOptions>({
      handle: {
        mode: "fill",
        suppressClearOnFillReduction: 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/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

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

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

[Live example: Fill Handle - Range Reduction](https://www.ag-grid.com/archive/36.2.0/examples/cell-selection-fill-handle/fill-handle-reduction/vue3/)

## Fill Handle Axis

By default, the Fill Handle can be dragged horizontally or vertically. If you wish to restrict the permitted direction of dragging to either horizontal or vertical, set `cellSelection.handle.direction` to either `x` for horizontal or `y` for vertical.

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

this.cellSelection = {
    handle: {
        mode: 'fill',
        direction: 'x', // Fill Handle can only be dragged horizontally
    }
};
```

#### Fill Handle - Direction

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

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

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

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div style="margin-bottom: 5px">
        <label>Axis: </label>
        <button class="ag-fill-direction xy" v-on:click="fillHandleAxis('xy')">xy</button>
        <button class="ag-fill-direction x selected" v-on:click="fillHandleAxis('x')">x only</button>
        <button class="ag-fill-direction y" v-on:click="fillHandleAxis('y')">y only</button>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :cellSelection="cellSelection"
        :rowData="rowData"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", minWidth: 150 },
      { field: "age", maxWidth: 90 },
      { field: "country", minWidth: 150 },
      { field: "year", maxWidth: 90 },
      { field: "date", minWidth: 150 },
      { field: "sport", minWidth: 150 },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      editable: true,
      cellDataType: false,
    });
    const cellSelection = ref<boolean | CellSelectionOptions>({
      handle: {
        mode: "fill",
        direction: "x",
      },
    });
    const rowData = ref<IOlympicData[]>(null);

    function fillHandleAxis(direction: "x" | "y" | "xy") {
      const buttons = Array.prototype.slice.call(
        document.querySelectorAll(".ag-fill-direction"),
      );
      const button = document.querySelector(".ag-fill-direction." + direction)!;
      buttons.forEach((btn) => {
        btn.classList.remove("selected");
      });
      button.classList.add("selected");
      gridApi.value.setGridOption("cellSelection", {
        handle: {
          mode: "fill",
          direction,
        },
      });
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

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

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

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

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

[Live example: Fill Handle - Direction](https://www.ag-grid.com/archive/36.2.0/examples/cell-selection-fill-handle/fill-handle-direction/vue3/)

## Double-Click Fill

When the fill handle direction is `'y'` or `'xy'`, double-clicking on the fill handle will perform a fill operation on all cells below the selected cells. Similarly, when the fill handle direction is `'x'`, double-clicking on the fill handle will perform a fill operation on all cells to the right of the selected cells.

This is enabled by default when the fill handle is enabled and does not require separate configuration.

## Fill Handle Events

When using the fill handle the grid will fire the `fillStart` event before it starts filling cells and the `fillEnd` event when all cells have been filled.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `fillStart` | `FillStartEvent` |  |  |  |
| `fillEnd` | `FillEndEvent` |  |  |  |

## Custom User Function

Often there is a need to use a custom method to fill values instead of simply copying values or increasing number values using linear progression. In these scenarios, the `cellSelection.handle.setFillValue` callback should be used.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `setFillValue` | `SetFillValueCallback` |  |  |  |

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

this.cellSelection = {
    handle: {
        mode: 'fill',
        setFillValue(params) {
            if (params.column.getColId() !== 'dayOfTheWeek') {
                return params.useDefault();
            }

            const daysList = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
            const lastValue = params.values[params.values.length - 1];
            const idxOfLast = daysList.indexOf(lastValue);
            return params.useValue(daysList[(idxOfLast + 1) % daysList.length]);
        },
    },
};
```

### FillOperationParams

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

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `event` | `MouseEvent` |  |  |  |
| `values` | `any[]` |  |  |  |
| `rowNode` | `IRowNode` |  |  |  |
| `column` | `Column` |  |  |  |
| `initialValues` | `any[]` |  |  |  |
| `initialNonAggregatedValues` | `any[]` |  |  |  |
| `initialFormattedValues` | `any[]` |  |  |  |
| `currentIndex` | `number` |  |  |  |
| `currentCellValue` | `any` |  |  |  |
| `direction` | `'up' \| 'down' \| 'left' \| 'right'` |  |  |  |
| `useValue` | `Function` |  |  |  |
| `skipCell` | `Function` |  |  |  |
| `useDefault` | `Function` |  |  |  |
| `api` | `GridApi` |  |  |  |
| `context` | `TContext` |  |  |  |

Use the callback helpers to state how each cell should be handled:

- `params.useValue(value)` uses the value and adds it to `params.values` for the next callback.
- `params.skipCell()` leaves the cell unchanged and does not add it to `params.values`.
- `params.useDefault()` lets the grid calculate the value using its default Fill Handle behaviour.

In the example below the **Day of the Week** column cycles through the days, while every other column is left to the grid's default behaviour. Select `Sunday` in the first row and drag the Fill Handle down. The callback's first result, `Monday`, already matches the value in the target cell; `params.useValue('Monday')` still adds it to the sequence, so the next result is `Tuesday`.

#### Custom Fill Operation

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  CellSelectionOptions,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { CellSelectionModule } from "ag-grid-enterprise";

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

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

const daysList = [
  "Sunday",
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
];

// days deliberately out of order, so filling the column visibly reorders them
const initialDays = [
  "Sunday",
  "Monday",
  "Friday",
  "Thursday",
  "Tuesday",
  "Saturday",
  "Wednesday",
];

function addDayOfTheWeek(rowData: any[]) {
  return rowData.map((row, index) => ({
    ...row,
    dayOfTheWeek: initialDays[index % initialDays.length],
  }));
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :cellSelection="cellSelection"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", minWidth: 150 },
      { headerName: "Day of the Week", field: "dayOfTheWeek", minWidth: 180 },
      { field: "age", maxWidth: 90 },
      { field: "country", minWidth: 150 },
      { field: "year", maxWidth: 90 },
      { field: "sport", minWidth: 150 },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      editable: true,
      cellDataType: false,
    });
    const cellSelection = ref<boolean | CellSelectionOptions>({
      handle: {
        mode: "fill",
        setFillValue(params) {
          if (params.column.getColId() !== "dayOfTheWeek") {
            // every other column keeps the default Fill Handle behaviour
            return params.useDefault();
          }
          const lastValue = params.values[params.values.length - 1];
          const idxOfLast = daysList.indexOf(lastValue);
          return params.useValue(daysList[(idxOfLast + 1) % daysList.length]);
        },
      },
    });
    const rowData = ref<any[]>(null);

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

      const updateData = (data) =>
        params.api.setGridOption("rowData", addDayOfTheWeek(data));

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

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

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

[Live example: Custom Fill Operation](https://www.ag-grid.com/archive/36.2.0/examples/cell-selection-fill-handle/custom-fill-operation/vue3/)

### Skipping Columns in the Fill Operation

The example below uses `params.skipCell()` to prevent values in the **Country** column from being altered by the Fill Handle.

Directly returning a value equal to `params.currentCellValue` also skips the cell but prefer `params.skipCell()`, which skips the cell explicitly regardless of the value it holds.

#### Skipping Columns

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  CellSelectionOptions,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { CellSelectionModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :cellSelection="cellSelection"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", minWidth: 150 },
      { field: "age", maxWidth: 90 },
      { field: "country", minWidth: 150 },
      { field: "year", maxWidth: 90 },
      { field: "date", minWidth: 150 },
      { field: "sport", minWidth: 150 },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      editable: true,
      cellDataType: false,
    });
    const cellSelection = ref<boolean | CellSelectionOptions>({
      handle: {
        mode: "fill",
        suppressClearOnFillReduction: true,
        setFillValue(params) {
          if (params.column.getColId() === "country") {
            return params.skipCell();
          }
          return params.useDefault();
        },
      },
    });
    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/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

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

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

[Live example: Skipping Columns](https://www.ag-grid.com/archive/36.2.0/examples/cell-selection-fill-handle/skipping-columns/vue3/)

> **Warning**
>
> Non editable cells will **not** be changed by the Fill Handle, so there is no need to add custom logic to skip columns that aren't editable.

## Read Only Edit

When the grid is in [Read Only Edit](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/value-setters/#read-only-edit) mode the Fill Handle will not update the data inside the grid. Instead the grid fires `cellEditRequest` events allowing the application to process the update request.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `cellEditRequest` | `CellEditRequestEvent` |  |  |  |

The example below will show how to update cell value combining the Fill Handle with `readOnlyEdit=true`.

#### Fill Handle - ReadOnlyEdit

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  CellEditRequestEvent,
  CellSelectionOptions,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GetRowIdFunc,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  TextEditorModule,
  enableDevValidations,
} from "ag-grid-community";
import { CellSelectionModule } from "ag-grid-enterprise";
import { IOlympicDataWithId } from "./interfaces";

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

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

let rowImmutableStore: any[];

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :cellSelection="cellSelection"
      :readOnlyEdit="true"
      :getRowId="getRowId"
      :rowData="rowData"
      @cell-edit-request="onCellEditRequest"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicDataWithId> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", minWidth: 160 },
      { field: "age" },
      { field: "country", minWidth: 140 },
      { field: "year" },
      { field: "date", minWidth: 140 },
      { field: "sport", minWidth: 160 },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      editable: true,
      cellDataType: false,
    });
    const cellSelection = ref<boolean | CellSelectionOptions>({
      handle: {
        mode: "fill",
      },
    });
    const getRowId = ref<GetRowIdFunc>((params) => String(params.data.id));
    const rowData = ref<IOlympicDataWithId[]>(null);

    function onCellEditRequest(event: CellEditRequestEvent) {
      const data = event.data;
      const field = event.colDef.field;
      const newValue = event.newValue;
      const oldItem = rowImmutableStore.find((row) => row.id === data.id);
      if (!oldItem || !field) {
        return;
      }
      const newItem = { ...oldItem };
      newItem[field] = newValue;
      console.log("onCellEditRequest, updating " + field + " to " + newValue);
      rowImmutableStore = rowImmutableStore.map((oldItem) =>
        oldItem.id == newItem.id ? newItem : oldItem,
      );
      gridApi.value.setGridOption("rowData", rowImmutableStore);
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        data.forEach((item, index) => (item.id = index));
        rowImmutableStore = data;
        params.api.setGridOption("rowData", rowImmutableStore);
      };

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

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      cellSelection,
      getRowId,
      rowData,
      onGridReady,
      onCellEditRequest,
    };
  },
});

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

[Live example: Fill Handle - ReadOnlyEdit](https://www.ag-grid.com/archive/36.2.0/examples/cell-selection-fill-handle/read-only-edit/vue3/)

## Suppressing the Fill Handle

The Fill Handle can be disabled on a per column basis by setting the column definition property `suppressFillHandle` to `true`.

In the example below, please note that the Fill Handle is disabled in the **Country** and **Date** columns.

#### Suppress Fill Handle

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

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

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

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :cellSelection="cellSelection"
        :rowData="rowData"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", minWidth: 150 },
      { field: "age", maxWidth: 90 },
      { field: "country", minWidth: 150, suppressFillHandle: true },
      { field: "year", maxWidth: 90 },
      { field: "date", minWidth: 150, suppressFillHandle: true },
      { field: "sport", minWidth: 150 },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      editable: true,
      cellDataType: false,
    });
    const cellSelection = ref<boolean | CellSelectionOptions>({
      handle: { mode: "fill" },
    });
    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/small-olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

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

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

[Live example: Suppress Fill Handle](https://www.ag-grid.com/archive/36.2.0/examples/cell-selection-fill-handle/suppress-fill-handle/vue3/)

## API Reference

Here you can find a full list of configuration options available when the handle options are in `'fill'` mode.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `mode` | `'fill'` |  |  |  |
| `suppressClearOnFillReduction` | `boolean` |  |  |  |
| `direction` | `'x' \| 'y' \| 'xy'` |  |  |  |
| `setFillValue` | `SetFillValueCallback` |  |  |  |
