---
title: "Row Pagination"
framework: vue
version: "36.1.0"
---

# Row Pagination

Pagination allows the grid to paginate rows, removing the need for a vertical scroll to view more data.

To enable pagination set the grid property `pagination=true`.

#### Client Paging

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  PaginationModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([PaginationModule, ClientSideRowModelModule]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :pagination="true"
      :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: 170,
      },
      { field: "age" },
      { field: "country" },
      { field: "date" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    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: Client Paging](https://www.ag-grid.com/examples/row-pagination/client-paging/vue3)

## Supported Row Models

Pagination in AG Grid is supported in [all the different row models](https://www.ag-grid.com/vue-data-grid/row-models/). The [Client-Side Row Model](https://www.ag-grid.com/vue-data-grid/row-models/#client-side) (the default row model) is used for the examples on this page.

To see the specifics of pagination on the other row models check the relevant documentation for [Infinite Row Model](https://www.ag-grid.com/vue-data-grid/infinite-scrolling/#pagination), [Viewport Row Model](https://www.ag-grid.com/vue-data-grid/viewport/#example-viewport-with-pagination) and [Server-Side Row Model](https://www.ag-grid.com/vue-data-grid/server-side-model-pagination/).

## Styling the Pagination Panel

The height of the pagination panel defaults to the grid row height. Use the `paginationPanelHeight` [theme parameter](https://www.ag-grid.com/vue-data-grid/theming-parameters/) to change the height.

The pagination panel can be styled with CSS, use the class `ag-paging-panel` to target the pagination panel. Use browser developer tools to find class names for specific elements within the pagination panel.

## Pagination Panel Layout

The pagination panel is composed of built-in components that can be individually reordered or hidden via the `paginationPanels` grid option:

- `pageSize` — the page size selector dropdown.
- `rowSummary` — the row range summary (e.g. `1 to 10 of 50`).
- `pageSummary` — navigation buttons (first, previous, next, last) with an editable page number input for direct page navigation. Use `{ type: 'pageSummary', suppressPageInput: true }` to show a read-only page number instead.
- `pageNumbers` — numbered page buttons for direct navigation, with ellipses for large page counts (e.g. `1 … 9 10 11 … 51`). Opt-in: not included in the default panels.

The default order is: `['pageSize', 'rowSummary', 'pageSummary']`.

See [Example: Customising Pagination](#example-customising-pagination) for a live demonstration of reordering the pagination panels.

```js
// Render the page navigation first, then the row summary, then the page size selector
const paginationPanels = ['pageSummary', 'rowSummary', 'pageSize'];
```

> **Note**
>
> When a panel is omitted from `paginationPanels`, its accessibility announcements are also omitted.

### Suppressing the Page Input

To disable the editable page input and show a read-only page number instead, use the object form of the `pageSummary` entry with `suppressPageInput: true`:

```js
paginationPanels: [
    'rowSummary',
    { type: 'pageSummary', suppressPageInput: true },
    'pageSize',
]
```

## Number Formats

The numbers within the Paging Toolbar can be formatted in two ways:

- For thousand and decimal separator changes, customise [Localisation](https://www.ag-grid.com/vue-data-grid/localisation/).
- For full control over each number's rendering, use the `paginationNumberFormatter` callback — see [Example: Customising Pagination](#example-customising-pagination).

## Example: Auto Page Size

If you set `paginationAutoPageSize=true` the grid will automatically show as many rows in each page as it can fit. This is demonstrated below. Note if you resize the display area of the grid, the page size automatically changes. To view this, open the example up in a new tab and resize your browser.

#### Auto Page Size

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  PaginationModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([PaginationModule, ClientSideRowModelModule]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :paginationAutoPageSize="true"
      :pagination="true"
      :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: 170,
      },
      { field: "age" },
      { field: "country" },
      { field: "date" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    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: Auto Page Size](https://www.ag-grid.com/examples/row-pagination/auto-page-size/vue3)

> **Note**
>
> Each pagination page must have the same number of rows. If you use `paginationAutoPageSize` with auto row height or dynamic row height via the [getRowHeight()](https://www.ag-grid.com/vue-data-grid/row-height/#getrowheight-callback) callback, the page height will be calculated using the default row height and not the actual row heights. Therefore the rows will not fit perfectly into the page if these features are mixed.

> **Note**
>
> When `paginationAutoPageSize` is used, the grid will not show the page size dropdown selector in the pagination panel, and the option `paginationPageSizeSelector` will be ignored.

## Example: Customising Pagination

In this example the default pagination settings are changed. Note the following:

- `paginationPageSizeSelector` is set to `[200, 500, 1000]`
- `paginationPageSize` is set to `500`
- `paginationPanels` is set to `[{ type: 'pageSummary', suppressPageInput: true }, 'rowSummary', 'pageSize']` to reorder the pagination controls and suppress the page number input.
- The numbers in the pagination panel are formatted differently using the grid callback `paginationNumberFormatter` and putting the numbers into square brackets i.e. [x].
- `api.paginationGoToPage(4)` is called to go to page 4 (0 based, so the 5th page)

#### Custom Paging

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  PaginationModule,
  PaginationNumberFormatter,
  PaginationNumberFormatterParams,
  PaginationPanel,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([PaginationModule, ClientSideRowModelModule]);

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"
        :pagination="true"
        :paginationPageSize="paginationPageSize"
        :paginationPageSizeSelector="paginationPageSizeSelector"
        :paginationPanels="paginationPanels"
        :paginationNumberFormatter="paginationNumberFormatter"
        :rowData="rowData"
        @first-data-rendered="onFirstDataRendered"></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: 170,
      },
      { field: "age" },
      { field: "country" },
      { field: "date" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    const paginationPageSize = ref(500);
    const paginationPageSizeSelector = ref<number[] | boolean>([
      200, 500, 1000,
    ]);
    const paginationPanels = ref<PaginationPanel[]>([
      { type: "pageSummary", suppressPageInput: true },
      "rowSummary",
      "pageSize",
    ]);
    const paginationNumberFormatter = ref<PaginationNumberFormatter>(
      (params: PaginationNumberFormatterParams) => {
        return "[" + params.value.toLocaleString() + "]";
      },
    );
    const rowData = ref<IOlympicData[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      params.api.paginationGoToPage(4);
    }
    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,
      paginationPageSize,
      paginationPageSizeSelector,
      paginationPanels,
      paginationNumberFormatter,
      rowData,
      onGridReady,
      onFirstDataRendered,
    };
  },
});

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

[Live example: Custom Paging](https://www.ag-grid.com/examples/row-pagination/custom-paging/vue3)

## Example: Page Number Navigation

The `pageNumbers` panel renders a numbered button for each page, letting users jump straight to one. It is opt-in: register `PaginationPageNumbersModule` and add the panel to `paginationPanels`:

```js
import { PaginationPageNumbersModule } from 'ag-grid-community';

ModuleRegistry.registerModules([ PaginationModule, PaginationPageNumbersModule ]);

const gridOptions = {
    paginationPanels: ['pageNumbers']
}
```

The example below demonstrates page number navigation:

#### Page Number Navigation

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  PaginationModule,
  PaginationPageNumbersModule,
  PaginationPanel,
  ValidationModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  PaginationModule,
  PaginationPageNumbersModule,
  ClientSideRowModelModule,
  ...(process.env.NODE_ENV !== "production" ? [ValidationModule] : []),
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :pagination="true"
      :paginationPageSize="paginationPageSize"
      :paginationPageSizeSelector="paginationPageSizeSelector"
      :paginationPanels="paginationPanels"
      :rowData="rowData"
      @first-data-rendered="onFirstDataRendered"></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: 170 },
      { field: "age" },
      { field: "country" },
      { field: "date" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    const paginationPageSize = ref(100);
    const paginationPageSizeSelector = ref<number[] | boolean>([50, 100, 200]);
    const paginationPanels = ref<PaginationPanel[]>([
      "rowSummary",
      "pageNumbers",
      "pageSize",
    ]);
    const rowData = ref<IOlympicData[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      params.api.paginationGoToPage(9);
    }
    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,
      paginationPageSize,
      paginationPageSizeSelector,
      paginationPanels,
      rowData,
      onGridReady,
      onFirstDataRendered,
    };
  },
});

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

[Live example: Page Number Navigation](https://www.ag-grid.com/examples/row-pagination/page-numbers/vue3)

## Example: Custom Pagination Controls

If you set `suppressPaginationPanel=true`, the grid will not show the standard navigation controls for pagination. This is useful if you want to provide your own navigation controls.

In the example below you can see how this works. Note that we are listening to `onPaginationChanged` to update the information about the current pagination status. We also call methods on the pagination API to change the pagination state.

The example also shows how the grid handles the case where the requested page doesn't exist. In this case, when the users requests page 50, the grid will show the last page (page 18 in this example).

A list of the API methods and events can be found in the [Pagination API section](#pagination-api).

The example also sets property `suppressScrollOnNewData=true`, which tells the grid to NOT scroll to the top when the page changes.

#### Custom Controls

```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,
  PaginationModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([PaginationModule, ClientSideRowModelModule]);

function setText(selector: string, text: any) {
  (document.querySelector(selector) as any).innerHTML = text;
}

function setLastButtonDisabled(disabled: boolean) {
  (document.querySelector("#btLast") as any).disabled = disabled;
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div class="example-header">
        <div>
          <button v-on:click="onBtFirst()">To First</button>
          <button v-on:click="onBtLast()" id="btLast">To Last</button>
          <button v-on:click="onBtPrevious()">To Previous</button>
          <button v-on:click="onBtNext()">To Next</button>
          <button v-on:click="onBtPageFive()">To Page 5</button>
          <button v-on:click="onBtPageFifty()">To Page 50</button>
        </div>
        <div style="margin-top: 6px">
          <span class="label">Last Page Found:</span>
          <span class="value" id="lbLastPageFound">-</span>
          <span class="label">Page Size:</span>
          <span class="value" id="lbPageSize">-</span>
          <span class="label">Total Pages:</span>
          <span class="value" id="lbTotalPages">-</span>
          <span class="label">Current Page:</span>
          <span class="value" id="lbCurrentPage">-</span>
        </div>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :paginationPageSize="paginationPageSize"
        :paginationPageSizeSelector="paginationPageSizeSelector"
        :pagination="true"
        :suppressPaginationPanel="true"
        :suppressScrollOnNewData="true"
        :rowData="rowData"
        @pagination-changed="onPaginationChanged"></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: 170,
      },
      { field: "age" },
      { field: "country" },
      { field: "date" },
      { field: "total" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
    });
    const paginationPageSize = ref(500);
    const paginationPageSizeSelector = ref<number[] | boolean>([
      100, 500, 1000,
    ]);
    const rowData = ref<IOlympicData[]>(null);

    function onPaginationChanged() {
      console.log("onPaginationPageLoaded");
      // Workaround for bug in events order
      if (gridApi.value!) {
        setText("#lbLastPageFound", gridApi.value!.paginationIsLastPageFound());
        setText("#lbPageSize", gridApi.value!.paginationGetPageSize());
        // we +1 to current page, as pages are zero based
        setText(
          "#lbCurrentPage",
          gridApi.value!.paginationGetCurrentPage() + 1,
        );
        setText("#lbTotalPages", gridApi.value!.paginationGetTotalPages());
        setLastButtonDisabled(!gridApi.value!.paginationIsLastPageFound());
      }
    }
    function onBtFirst() {
      gridApi.value!.paginationGoToFirstPage();
    }
    function onBtLast() {
      gridApi.value!.paginationGoToLastPage();
    }
    function onBtNext() {
      gridApi.value!.paginationGoToNextPage();
    }
    function onBtPrevious() {
      gridApi.value!.paginationGoToPreviousPage();
    }
    function onBtPageFive() {
      // we say page 4, as the first page is zero
      gridApi.value!.paginationGoToPage(4);
    }
    function onBtPageFifty() {
      // we say page 49, as the first page is zero
      gridApi.value!.paginationGoToPage(49);
    }
    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,
      paginationPageSize,
      paginationPageSizeSelector,
      rowData,
      onGridReady,
      onPaginationChanged,
      onBtFirst,
      onBtLast,
      onBtNext,
      onBtPrevious,
      onBtPageFive,
      onBtPageFifty,
    };
  },
});

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

[Live example: Custom Controls](https://www.ag-grid.com/examples/row-pagination/custom-controls/vue3)

## Pagination & Child Rows

Both [Row Grouping](https://www.ag-grid.com/vue-data-grid/grouping/) and [Master Detail](https://www.ag-grid.com/vue-data-grid/master-detail/) have rows that expand. When this happens, consideration needs to be given as to how this impacts the number of rows on the page. There are two modes of operation that can be used depending on what your application requirements.

### Mode 1: Paginate Only Top Level Rows

The first mode is the default. The rows are split according to the top level rows. For example if row grouping with a page size of 10, then each page will contain 10 top level groups. When expanding a group with this mode, all children for that group, along with the 10 original groups for that page, will get displayed in one page. This will result in a page size greater than the initial page size of 10 rows.

This mode is typically best suited for Row Grouping as children are always displayed alongside the parent group. It is also typically best for Master Detail, as detail rows (that typically contain detail tables) will always appear below their master rows.

In the example below, note the following:

- Each page will always contain exactly 10 groups.
- Expanding a group will not push rows to the next page.

#### Grouping Normal

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  PaginationModule,
  enableDevValidations,
} from "ag-grid-community";
import { RowGroupingModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  PaginationModule,
  ClientSideRowModelModule,
  RowGroupingModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :pagination="true"
      :paginationPageSize="paginationPageSize"
      :paginationPageSizeSelector="paginationPageSizeSelector"
      :defaultColDef="defaultColDef"
      :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" },
      { field: "age" },
      { field: "country", rowGroup: true },
      { field: "year", rowGroup: true },
      { field: "date" },
      { field: "sport", rowGroup: true },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
      { field: "total" },
    ]);
    const paginationPageSize = ref(10);
    const paginationPageSizeSelector = ref<number[] | boolean>([
      10, 20, 50, 100,
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 190,
    });
    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,
      paginationPageSize,
      paginationPageSizeSelector,
      defaultColDef,
      rowData,
      onGridReady,
    };
  },
});

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

[Live example: Grouping Normal](https://www.ag-grid.com/examples/row-pagination/grouping-normal/vue3)

### Mode 2: Paginate All Rows, Including Children

The second mode paginates all rows, including child rows when Row Grouping and detail rows with Master Detail. For example if row grouping with a page size of 10, then each page will always contain exactly 10 rows, even if it means having children appear on a page after the page containing the parent. This can be particularly confusing if the last row of a page is expanded, as the children will appear on the next page (not visible to the user unless they navigate to the next page).

This mode is typically best if the application never wants to exceed the maximum number of rows in a page past the page size. This can be helpful if designing for touch devices (e.g. tablets) where UX requirements state no scrolls should be visible in the application - paging to a strict page size can guarantee no vertical scrolls will appear.

To enable pagination on all rows, including children, set grid property `paginateChildRows=true`.

In the example below, note the following:

- Each page will always contain exactly 10 rows (not groups).
- Expanding a group will push rows to the next page to limit the total number of rows to 10.

> **Note**
>
> When `paginateChildRows=true` the Grid automatically disables Group Rows Sticky, see: [suppressGroupRowsSticky](https://www.ag-grid.com/vue-data-grid/grid-options/#reference-rowGrouping-suppressGroupRowsSticky).

#### Grouping Paginate Child Rows

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  PaginationModule,
  enableDevValidations,
} from "ag-grid-community";
import { RowGroupingModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  PaginationModule,
  ClientSideRowModelModule,
  RowGroupingModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :pagination="true"
      :paginationPageSize="paginationPageSize"
      :paginationPageSizeSelector="paginationPageSizeSelector"
      :paginateChildRows="true"
      :defaultColDef="defaultColDef"
      :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" },
      { field: "age" },
      { field: "country", rowGroup: true },
      { field: "year", rowGroup: true },
      { field: "date" },
      { field: "sport", rowGroup: true },
      { field: "gold" },
      { field: "silver" },
      { field: "bronze" },
      { field: "total" },
    ]);
    const paginationPageSize = ref(10);
    const paginationPageSizeSelector = ref<number[] | boolean>([
      10, 20, 50, 100,
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 190,
    });
    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,
      paginationPageSize,
      paginationPageSizeSelector,
      defaultColDef,
      rowData,
      onGridReady,
    };
  },
});

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

[Live example: Grouping Paginate Child Rows](https://www.ag-grid.com/examples/row-pagination/grouping-paginate-child-rows/vue3)

### Fallback to Mode 2

If using either of the following features, the grid will be forced to use the second mode:

- [Hide Open Parents](https://www.ag-grid.com/vue-data-grid/grouping-multiple-group-columns/#hiding-expanded-parent-rows)
- [Hiding Parents of Individual Rows](https://www.ag-grid.com/vue-data-grid/grouping-data/#hiding-parents-of-individual-rows)

This is because both of these features remove top level rows (group rows and master rows) from the displayed rows, making it impossible to paginate based on the top level rows only.

## Pagination Properties

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `pagination` | `boolean` |  | `false` | Set whether pagination is enabled. See [Row Pagination](https://www.ag-grid.com/vue-data-grid/row-pagination/) for more information. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationPageSize` | `number` |  | `100` | How many rows to load per page. If `paginationAutoPageSize` is specified, this property is ignored. See [Customising Pagination](https://www.ag-grid.com/vue-data-grid/row-pagination/#example-customising-pagination) for more information. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationPageSizeSelector` | `number[] \| boolean` |  | `true` | Determines if the page size selector is shown in the pagination panel or not. Set to an array of values to show the page size selector with custom list of possible page sizes. Set to `true` to show the page size selector with the default page sizes `[20, 50, 100]`. Set to `false` to hide the page size selector. See [Customising Pagination](https://www.ag-grid.com/vue-data-grid/row-pagination/#example-customising-pagination) for more information. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationPanels` | `PaginationPanel[]` |  |  | Controls which built-in components appear in the pagination panel and in what order. Accepts an array of panel names (`'pageSize'`, `'rowSummary'`, `'pageSummary'`) or config objects. Components render in the order they appear in the array. Omitted components are hidden. An empty array hides the pagination panel entirely. When not set, all three components render in the default order: [`pageSize`, `rowSummary`, `pageSummary`]. Use `{ type: 'pageSummary', suppressPageInput: true }` to render a read-only page summary. See [Pagination Panel Layout](https://www.ag-grid.com/vue-data-grid/row-pagination/#pagination-panel-layout) for more information. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationNumberFormatter` | `PaginationNumberFormatter` |  |  | Allows user to format the numbers in the pagination panel, i.e. 'row count' and 'page number' labels. This is for pagination panel only, to format numbers inside the grid's cells (i.e. your data), then use `valueFormatter` in the column definitions. See [Customising Pagination](https://www.ag-grid.com/vue-data-grid/row-pagination/#example-customising-pagination) for more information. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). [Initial](https://www.ag-grid.com/vue-data-grid/grid-interface/#initial-grid-options). |
| `paginationAutoPageSize` | `boolean` |  | `false` | Set to `true` so that the number of rows to load per page is automatically adjusted by the grid so each page shows enough rows to just fill the area designated for the grid. If `false`, `paginationPageSize` is used. See [Auto Page Size](https://www.ag-grid.com/vue-data-grid/row-pagination/#example-auto-page-size) for more information. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginateChildRows` | `boolean` |  | `false` | Set to `true` to have pages split children of groups when using Row Grouping or detail rows with Master Detail. See [Pagination & Child Rows](https://www.ag-grid.com/vue-data-grid/row-pagination/#pagination--child-rows) for more information. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). [Initial](https://www.ag-grid.com/vue-data-grid/grid-interface/#initial-grid-options). |
| `suppressPaginationPanel` | `boolean` |  | `false` | If `true`, the default grid controls for navigation are hidden. This is useful if `pagination=true` and you want to provide your own pagination controls. Otherwise, when `pagination=true` the grid automatically shows the necessary controls at the bottom so that the user can navigate through the different pages. See [Custom Pagination Controls](https://www.ag-grid.com/vue-data-grid/row-pagination/#example-customising-pagination) for more information. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |

## Pagination API

> **Note**
>
> The pagination state can be saved and restored as part of [Grid State](https://www.ag-grid.com/vue-data-grid/grid-state/).

The following methods comprise the pagination API and are all available from `api`

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `paginationIsLastPageFound` | `Function` |  |  | Returns `true` when the last page is known; this will always be the case if you are using the Client-Side Row Model for pagination. Returns `false` when the last page is not known; this only happens when using [Infinite Row Model](https://www.ag-grid.com/vue-data-grid/infinite-scrolling/). Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationGetPageSize` | `Function` |  |  | Returns how many rows are being shown per page. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationGetCurrentPage` | `Function` |  |  | Returns the 0-based index of the page which is showing. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationGetTotalPages` | `Function` |  |  | Returns the total number of pages. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationGetRowCount` | `Function` |  |  | Returns the total number of pageable rows, as impacted by `gridOptions.paginateChildRows: true`. It is recommended to instead use `gridApi.getDisplayedRowCount()` if not using pagination, or if `gridOption.paginateChildRows=true`. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationGoToPage` | `Function` |  |  | Goes to the specified page. If the page requested doesn't exist, it will go to the last page. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationGoToNextPage` | `Function` |  |  | Navigates to the next page. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationGoToPreviousPage` | `Function` |  |  | Navigates to the previous page. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationGoToFirstPage` | `Function` |  |  | Navigates to the first page. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |
| `paginationGoToLastPage` | `Function` |  |  | Navigates to the last page. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). |

## Pagination Callbacks

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `paginationNumberFormatter` | `PaginationNumberFormatter` |  |  | Allows user to format the numbers in the pagination panel, i.e. 'row count' and 'page number' labels. This is for pagination panel only, to format numbers inside the grid's cells (i.e. your data), then use `valueFormatter` in the column definitions. Module: [`PaginationModule`](https://www.ag-grid.com/vue-data-grid/modules/). [Initial](https://www.ag-grid.com/vue-data-grid/grid-interface/#initial-grid-options). |

## Pagination Events

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `paginationChanged` | `PaginationChangedEvent` |  |  | Triggered every time the paging state changes. Some of the most common scenarios for this event to be triggered are:The page size changesThe current shown page is changedNew data is loaded onto the grid |
