React Pagination - Getting Started
Pagination is a UI component that allows users to navigate through pages and change page size at runtime.
This tutorial explains how to add Pagination to a page and configure the component's core settings. It also covers implementing remote pagination. Colored cards are loaded each time a user switches pages or changes page size. The final result is displayed below:
Each section in this tutorial describes a single configuration step. You can also find the full source code in the following GitHub repository:
Create Pagination
Add DevExtreme to your Vue application and use the following code to create a Pagination component:
- <template>
- <DxPagination />
- </template>
- <script setup lang="ts">
- import 'devextreme/dist/css/dx.light.css';
- import { DxPagination } from 'devextreme-vue/pagination';
- </script>
Configure Pagination
This tutorial step guides you through the basic Pagination setup.
Specify the following settings:
- itemCount sets the total number of items. Pagination does not function properly without this setting.
- pageIndex sets the initial page to display. This tutorial sets pageIndex to 3 (the default value is 1).
- allowedPageSizes specifies page sizes available to users. Modify this list as needed. Include
'all'
to allow users to display all items on one page. This tutorial uses the default value:[5, 10]
. - pageSize specifies the initial page size.
The following code snippet demonstrates how to apply the aforementioned settings:
- <template>
- <DxPagination
- :show-info="true"
- :show-navigation-buttons="true"
- v-model:page-index="pageIndex"
- v-model:page-size="pageSize"
- :item-count="total"
- />
- </template>
- <script setup lang="ts">
- // ...
- import { ref } from 'vue';
- const total = 100;
- const pageSize = ref(5);
- const pageIndex = ref(3);
- </script>
Implement Remote Pagination
This section explains how to implement remote pagination. Client code generates a color list and requests a remote service for cards representing color entries on the screen. The pagination component helps users browse the resulting color cards.
Implementation can be broken down into three steps:
- Generate 100 hex codes.
- Fetch color cards from The Color API service when necessary:
- On page load
- On page size changes
- On page index changes
- Display color cards obtained from the service.
Implement the first step. Generate 100 random pastel hex codes and add them to an array:
- <template>
- <!-- ... -->
- </template>
- <script setup lang="ts">
- // ...
- import { ref, onMounted } from 'vue';
- import { getRandomPastelColor } from '../assets/colorService';
- const hexCodes = ref<string[]>([]);
- const generateHexCodes = () => {
- for (let i = 0; i < total; i++) {
- hexCodes.value.push(getRandomPastelColor());
- }
- };
- onMounted(() => {
- generateHexCodes();
- });
- </script>
- export const getRandomPastelColor = (): string => {
- const hue = Math.floor(Math.random() * 360);
- const saturation = Math.random() * 0.4 + 0.2;
- const brightness = Math.random() * 0.3 + 0.7;
- return hsvToHex(hue, saturation, brightness);
- };
- const hsvToHex = (h: number, s: number, v: number): string => {
- let r: number, g: number, b: number;
- const i = Math.floor(h / 60) % 6;
- const f = h / 60 - i;
- const p = v * (1 - s);
- const q = v * (1 - f * s);
- const t = v * (1 - (1 - f) * s);
- switch (i) {
- case 0: [r, g, b] = [v, t, p]; break;
- case 1: [r, g, b] = [q, v, p]; break;
- case 2: [r, g, b] = [p, v, t]; break;
- case 3: [r, g, b] = [p, q, v]; break;
- case 4: [r, g, b] = [t, p, v]; break;
- case 5: [r, g, b] = [v, p, q]; break;
- default: throw new Error("Unexpected case in HSV to RGB conversion");
- }
- const toHex = (x: number): string => Math.round(x * 255).toString(16).padStart(2, '0');
- return `${toHex(r)}${toHex(g)}${toHex(b)}`;
- };
Fetch Data
The following code snippet demonstrates how to fetch data from the Color API:
- import axios from 'axios';
- const apiEndpoint = 'https://www.thecolorapi.com/id?hex=';
- export const fetchColorData = async (
- hex: string,
- ): Promise<{ name: string; image: string } | null> => {
- try {
- const response = await axios.get(`${apiEndpoint}${hex}`);
- return {
- name: response.data.name.value,
- image: response.data.image.bare,
- };
- } catch (error) {
- console.error(`Error fetching color for hex ${hex}:`, error);
- return null;
- }
- };
Render Items
The render function determines the subset of cards to be displayed and populates the array with images and alt strings.
- <template>
- <DxPagination ... />
- <div id="cards">
- <div v-for="color in visibleCards" :key="color.name">
- <img :src="color.image" :alt="color.name" />
- </div>
- </div>
- </template>
- <script setup lang="ts">
- // ...
- interface Color {
- image: string;
- name: string;
- }
- const visibleCards = ref([] as Color[]);
- const colorCache = new Map<string, Color>();
- const fetchColorsForPage = async () => {
- const startIndex = (pageIndex.value - 1) * pageSize.value;
- const endIndex = startIndex + pageSize.value;
- const hexSubset = hexCodes.value.slice(startIndex, endIndex);
- const promises = hexSubset.map((hex) => {
- if (colorCache.has(hex)) {
- return Promise.resolve(colorCache.get(hex));
- }
- return fetchColorData(hex).then((color) => {
- if (color) {
- colorCache.set(hex, color);
- }
- return color;
- });
- });
- try {
- const results = await Promise.all(promises);
- visibleCards.value = results.filter((color): color is Color => color !== null);
- } catch (error) {
- console.error('Error fetching colors:', error);
- }
- };
- onMounted(() => {
- // ...
- fetchColorsForPage();
- });
- </script>
- <style>
- #cards {
- display: flex;
- justify-content: center;
- flex-wrap: wrap;
- }
- </style>
Handle Page Size and Index Changes
The render function is called on every page index/size change:
- <template>
- <DxPagination ...
- @update:page-index="onPageIndexChange"
- @update:page-size="onPageSizeChange"
- />
- <!-- ... -->
- </template>
- <script setup lang="ts">
- // ...
- const onPageIndexChange = (value: number) => {
- pageIndex.value = value;
- fetchColorsForPage();
- };
- const onPageSizeChange = (value: number) => {
- pageSize.value = value;
- fetchColorsForPage();
- };
- </script>
Integrate LoadPanel
The following code integrate a load panel into the application. The panel appears when the app requests card data from the remote service. This step is optional.
To integrate the DevExtreme LoadPanel component:
- Add a LoadPanel to the code.
- Display it before calling the render function.
- Hide it after render.
- <template>
- <DxPagination ... />
- <!-- ... -->
- <DxLoadPanel
- v-model:visible="loadPanelVisible"
- :show-indicator="true"
- :show-pane="true"
- :hide-on-outside-click="false"
- >
- <DxPosition my="top" at="top" of="#cards" />
- </DxLoadPanel>
- </template>
- <script setup lang="ts">
- // ...
- import { DxLoadPanel, DxPosition } from 'devextreme-vue/load-panel';
- const loadPanelVisible = ref(false);
- const fetchColorsForPage = async () => {
- loadPanelVisible.value = true;
- const startIndex = (pageIndex.value - 1) * pageSize.value;
- const endIndex = startIndex + pageSize.value;
- const hexSubset = hexCodes.value.slice(startIndex, endIndex);
- const promises = hexSubset.map((hex) => {
- // ...
- });
- try {
- const results = await Promise.all(promises);
- visibleCards.value = results.filter((color): color is Color => color !== null);
- } catch (error) {
- console.error('Error fetching colors:', error);
- } finally {
- loadPanelVisible.value = false;
- }
- };
- // ...
- </script>
If you have technical questions, please create a support ticket in the DevExpress Support Center.