Vue 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 React application and use the following code to create a Pagination component:
- import React from 'react';
- import 'devextreme/dist/css/dx.light.css';
- import { Pagination } from 'devextreme-react/pagination';
- function App(): JSX.Element {
- return (
- <Pagination />
- );
- }
- export default App;
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:
- import React, { useState } from 'react';
- // ...
- const total = 100;
- function App(): JSX.Element {
- const [pageSize, setPageSize] = useState<number>(5);
- const [pageIndex, setPageIndex] = useState<number>(3);
- return (
- <Pagination
- showInfo={true}
- showNavigationButtons={true}
- pageIndex={pageIndex}
- pageSize={pageSize}
- itemCount={total}
- />
- );
- }
- export default App;
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:
- import React, { useState, useEffect } from 'react';
- import { getRandomPastelColor } from './colorService';
- // ...
- function App(): JSX.Element {
- // ...
- const hexCodes = useRef<string[]>([]);
- useEffect(() => {
- for (let i = 0; i < total; i++) {
- hexCodes.current.push(getRandomPastelColor());
- }
- }, []);
- return (
- <!-- ... -->
- );
- }
- export default App;
- 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");
- }
- function toHex(x: number): string {
- if (isNaN(x) || x < 0 || x > 1) {
- return '00';
- }
- return 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 async function fetchColorData(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.
- import React, { useState, useRef, useEffect } from 'react';
- // ...
- interface Color {
- image: string;
- name: string;
- }
- function App(): JSX.Element {
- // ...
- const [visibleCards, setVisibleCards] = useState<Color[]>([]);
- const colorsCache = useRef<Map<string, Color>>(new Map());
- const fetchColorsForPage = useCallback(async (): Promise<void> => {
- const startIndex = (pageIndex - 1) * pageSize;
- const endIndex = startIndex + pageSize;
- const hexSubset = hexCodes.current.slice(startIndex, endIndex);
- const promises = hexSubset.map((hex) => {
- if (colorsCache.current.has(hex)) {
- return Promise.resolve(colorsCache.current.get(hex));
- }
- return fetchColorData(hex).then((color) => {
- if (color) {
- colorsCache.current.set(hex, color);
- }
- return color;
- });
- });
- try {
- const results = await Promise.all(promises);
- const filteredColors = results.filter((color): color is Color => color !== null);
- setVisibleCards(filteredColors);
- } catch (error) {
- console.error('Error fetching colors:', error);
- }
- }, [pageIndex, pageSize]);
- useEffect(() => {
- fetchColorsForPage().catch((error) => {
- console.error('Error updating visible cards:', error);
- });
- }, [fetchColorsForPage]);
- return (
- <Pagination ... />
- <div id="cards">
- {visibleCards.map((color, index) => (
- <div key={index}>
- <img src={color.image} alt={color.name} />
- </div>
- ))}
- </div>
- );
- }
- export default App;
- #cards {
- display: flex;
- justify-content: center;
- flex-wrap: wrap;
- }
Handle Page Size and Index Changes
The render function is called on every page index/size change:
- import React, { useState, useRef, useEffect, useCallback } from 'react';
- // ...
- function App(): JSX.Element {
- // ...
- const onPageIndexChange = useCallback((value: number) => {
- setPageIndex(value);
- }, []);
- const onPageSizeChange = useCallback((value: number) => {
- setPageSize(value);
- }, []);
- return (
- <Pagination ...
- onPageIndexChange={onPageIndexChange}
- onPageSizeChange={onPageSizeChange}
- />
- <!-- ... -->
- );
- }
- export default App;
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.
- // ...
- import LoadPanel, { Position } from 'devextreme-react/load-panel';
- function App(): JSX.Element {
- // ...
- const [loadPanelVisible, setLoadPanelVisible] = useState<boolean>(false);
- const fetchColorsForPage = useCallback(async (): Promise<void> => {
- setLoadPanelVisible(true);
- const startIndex = (pageIndex - 1) * pageSize;
- const endIndex = startIndex + pageSize;
- const hexSubset = hexCodes.current.slice(startIndex, endIndex);
- const promises = hexSubset.map((hex) => {
- // ...
- });
- try {
- const results = await Promise.all(promises);
- const filteredColors = results.filter((color): color is Color => color !== null);
- setVisibleCards(filteredColors);
- } catch (error) {
- console.error('Error fetching colors:', error);
- } finally {
- setLoadPanelVisible(false);
- }
- }, [pageIndex, pageSize]);
- // ...
- return (
- <Pagination ... />
- <!-- ... -->
- <LoadPanel
- visible={loadPanelVisible}
- showIndicator={true}
- showPane={true}
- hideOnOutsideClick={false}
- >
- <Position my="top" at="top" of="#cards" />
- </LoadPanel>
- );
- }
- export default App;
If you have technical questions, please create a support ticket in the DevExpress Support Center.