Example T1268732
Visible to All Users

DevExtreme Pagination - Getting Started

This repository stores code for the following DevExpress tutorial: Getting Started with DevExtreme Pagination. The project creates a UI component that allows users to navigate through pages.

Pagination## Files to Review

Documentation

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

jQuery/src/index.js
JavaScript
/* eslint-disable no-console, default-case */ const total = 100; const hexCodes = []; const apiEndpoint = 'https://www.thecolorapi.com/id?hex='; const cache = new Map(); function fetchData(colorId) { return new Promise((resolve, reject) => { if (cache.has(colorId)) { resolve(cache.get(colorId)); } else { $.getJSON(apiEndpoint + colorId, (data) => { const colorData = { image: data.image.bare, name: data.name.value, }; cache.set(colorId, colorData); resolve(colorData); }).fail(() => { reject(new Error(`Error loading color for hex: ${colorId}`)); }); } }); } const getRandomPastelColor = () => { 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, s, v) => { let r = 0; let g = 0; let b = 0; const i = Math.floor(h / 60); 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 % 6) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; } const toHex = (x) => { const hex = Math.round(x * 255).toString(16); return hex.length === 1 ? `0${hex}` : hex; }; return toHex(r) + toHex(g) + toHex(b); }; const renderCards = async (pageSize, pageIndex) => { $('#cards').empty(); const startIndex = (pageIndex - 1) * pageSize; const endIndex = pageIndex * pageSize; const hexSubset = hexCodes.slice(startIndex, endIndex); const promises = hexSubset.map((hex) => fetchData(hex)); try { const pageColors = await Promise.all(promises); pageColors.forEach((color) => { const image = $('<img>').attr({ src: color.image, alt: color.name, }); $('#cards').append(image); }); } catch (error) { console.error('Error rendering cards:', error); } }; $(() => { for (let i = 0; i < total; i += 1) { hexCodes.push(getRandomPastelColor()); } const loadPanel = $('#load-panel') .dxLoadPanel({ position: { my: 'top', at: 'top', of: '#cards', }, visible: false, showIndicator: true, showPane: true, hideOnOutsideClick: false, }) .dxLoadPanel('instance'); const pagination = $('#pagination') .dxPagination({ showInfo: true, showNavigationButtons: true, itemCount: total, pageIndex: 3, pageSize: 5, onOptionChanged: (e) => { if (e.name === 'pageSize' || e.name === 'pageIndex') { const pageIndex = pagination.option('pageIndex'); const pageSize = pagination.option('pageSize'); loadPanel.show(); renderCards(pageSize, pageIndex).finally(() => loadPanel.hide()); } }, }) .dxPagination('instance'); const pageSize = pagination.option('pageSize'); const pageIndex = pagination.option('pageIndex'); loadPanel.show(); renderCards(pageSize, pageIndex).finally(() => loadPanel.hide()); });
Angular/src/app/app.component.html
HTML
<div class="container"> <dx-load-panel [(visible)]="loadPanelVisible" [showIndicator]="true" [showPane]="true" [hideOnOutsideClick]="false" ><dxo-position my="top" at="top" of="#cards"> </dxo-position> </dx-load-panel> <dx-pagination [showInfo]="true" [showNavigationButtons]="true" [itemCount]="total" [pageIndex]="pageIndex" [pageSize]="pageSize" (pageIndexChange)="onPageIndexChange($event)" (pageSizeChange)="onPageSizeChange($event)" > </dx-pagination> <div id="cards"> <ng-container *ngFor="let color of visibleCards"> <img [src]="color.image" [alt]="color.name" /> </ng-container> </div> </div>
Angular/src/app/app.component.ts
TypeScript
/* eslint-disable @typescript-eslint/no-non-null-assertion, no-else-return, no-console, no-void */ import { Component } from '@angular/core'; import { firstValueFrom } from 'rxjs'; import { ColorService, Color } from './app.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], providers: [ColorService], }) export class AppComponent { loadPanelVisible = false; total = 100; colors: Map<string, Color> = new Map(); hexCodes: string[] = []; visibleCards: Color[] = []; pageIndex = 3; pageSize = 5; constructor(private readonly colorService: ColorService) {} ngOnInit(): void { this.generateHexCodes(); void this.fetchColorsForPage(); } generateHexCodes(): void { for (let i = 0; i < this.total; i++) { this.hexCodes.push(this.colorService.getRandomPastelColor()); } } async fetchColorsForPage(): Promise<void> { const startIndex = (this.pageIndex - 1) * this.pageSize; const endIndex = this.pageIndex * this.pageSize; const hexSubset = this.hexCodes.slice(startIndex, endIndex); const promises: Promise<Color>[] = hexSubset.map((hex) => { if (this.colors.has(hex)) { return Promise.resolve(this.colors.get(hex)!); } else { return firstValueFrom(this.colorService.fetchColorData(hex)).then((data) => { const colorData: Color = data; this.colors.set(hex, colorData); return colorData; }); } }); this.loadPanelVisible = true; try { const fetchedColors = await Promise.all(promises); this.visibleCards = fetchedColors; } catch (error) { console.error('Error fetching colors:', error); } finally { this.loadPanelVisible = false; } } onPageIndexChange(val: number): void { this.pageIndex = val; void this.fetchColorsForPage(); } onPageSizeChange(val: number): void { this.pageSize = val; void this.fetchColorsForPage(); } }
Vue/src/components/HomeContent.vue
Code
<template> <div class="container"> <DxLoadPanel v-model:visible="loadPanelVisible" :show-indicator="true" :show-pane="true" :hide-on-outside-click="false" > <DxPosition my="top" at="top" of="#cards" /> </DxLoadPanel> <DxPagination :show-info="true" :show-navigation-buttons="true" v-model:page-index="pageIndex" v-model:page-size="pageSize" :item-count="total" @update:page-index="onPageIndexChange" @update:page-size="onPageSizeChange" /> <div id="cards"> <div v-for="color in visibleCards" :key="color.name"> <img :src="color.image" :alt="color.name" /> </div> </div> </div> </template> <script setup lang="ts"> import 'devextreme/dist/css/dx.light.css'; import { ref, onMounted } from 'vue'; import { fetchColorData, getRandomPastelColor } from '../assets/colorService'; import { DxPagination } from 'devextreme-vue'; import { DxLoadPanel, DxPosition } from 'devextreme-vue/load-panel'; interface Color { image: string; name: string; } const total = 100; const pageSize = ref(5); const pageIndex = ref(3); const loadPanelVisible = ref(false); const visibleCards = ref([] as Color[]); const hexCodes = ref<string[]>([]); const colorCache = new Map<string, Color>(); const generateHexCodes = () => { for (let i = 0; i < total; i++) { hexCodes.value.push(getRandomPastelColor()); } }; 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) => { 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); } finally { loadPanelVisible.value = false; } }; const onPageIndexChange = (value: number) => { pageIndex.value = value; fetchColorsForPage(); }; const onPageSizeChange = (value: number) => { pageSize.value = value; fetchColorsForPage(); }; onMounted(() => { generateHexCodes(); fetchColorsForPage(); }); </script> <style> #cards { display: flex; justify-content: center; flex-wrap: wrap; } </style>

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.