GrPagination

  • ядро
  • Навигация
  • API · 14 props
  • ⌨ клавиши

Берут, когда список не помещается на экран.

import { GrPagination } from '@feugene/granularity/components/GrPagination'

Обзор

Когда брать

  • список не помещается на экран — номера страниц с усечением середины;
  • пользователь выбирает размер страницы — showPageSize с набором из pageSizes;
  • нужно знать объём — showTotal печатает «41–60 из 137» рядом с навигацией;
  • места мало — compact заменяет номера индикатором «текущая / всего»;
  • страниц много — showJumper даёт переход по номеру вместо перебора.

Когда взять другое

НужноБерите
Список подгружается прокруткойGrList с virtual и source
Строк мало и все помещаютсяGrTable
Переключаются разделы, а не страницы данныхGrTabs
Нужно показать ход длинной операцииGrProgressBar

page, pageSize и total приходят снаружи: компонент только просит их изменить. Он ничего не знает про данные и не может знать — их грузит приложение.

Playground контролы выводятся из API, а не пишутся руками

Сцена

Загружается…

0 изменено· состояние — в адресе

Примеры 3 у каждого — живое демо и его код

  • Таблица заказов со своим подвалом

    Компонент берёт итог и размер страницы и вычисляет остальное — число страниц не проп: два источника одной правды расходятся на первом же фильтре. show-total отвечает «сколько всего» — слот total формулирует это для заказов, — show-page-size меняет страницы на прокрутку, а sibling-count="0" держит подвал в одну строку.

    #4821Tailspin ToysOverdue€217.25
    #4820Wingtip ToysPaid€180.00
    #4819Adventure WorksShipped€143.75
    #4818Northwind TradersRefunded€106.50
    #4817Contoso LtdOverdue€69.25
    #4816Fabrikam IncPaid€932.00
    #4815Tailspin ToysShipped€895.75
    #4814Wingtip ToysRefunded€858.50
    #4813Adventure WorksOverdue€821.25
    #4812Northwind TradersPaid€784.00
  • Журнал аудита на 122 страницы

    При 122 страницах номер часто известен — из ссылки в тикете, — поэтому show-jumper принимает его сразу: наберите 97 и нажмите Enter. Первая и последняя страницы остаются под рукой вокруг текущей.

    Audit log2,431 security events of the workspace · newest first
    23:57Daniel Kim invited a memberevt_2391
    22:50Grace Wu signed inevt_2390
    21:43Jonas Weber invited a memberevt_2389
    20:36Mina Ortiz signed inevt_2388
    19:29Daniel Kim invited a memberevt_2387
    18:22Grace Wu signed inevt_2386
  • Отзывы на телефоне

    На телефоне ряд номеров и не помещается, и не помогает: compact оставляет стрелки и «3 / 14».

    Reviews · 4.6 ★ from 42
    Grace W. · ★★★★★Bought a second one in navy.

API порождается из пакета · разойтись не может

Props

PropTypeпо умолчаниюОписание
disabledboolean | undefinedfalseГасит всю пагинацию: номера, кнопки, селект размера и поле перехода.
size"xs" | "sm" | "md" | "lg" | undefinedundefinedВысота кнопок, поля перехода и селекта по шкале контролов. Не задан — из `GrConfigProvider`, иначе `md`.
ariaLabelstring | undefinedundefinedИмя навигационного лендмарка. По умолчанию — `gr.pagination.label`; задавать стоит там, где пагинаций на странице несколько и их надо различать.
compactboolean | undefinedfalseКомпактный вариант: вместо нумерованных страниц показывается индикатор «текущая / всего» — удобно для узких мест (мобайл, тулбары таблиц).
pageSizesGrPaginationPageSizeOption[] | undefined[10, 20, 50]Варианты размера страницы. Число — подпись равна значению; пара — своя подпись при том же значении («50 / стр.»), которую иначе было не собрать.
siblingCountnumber | undefined1Сколько соседних страниц показывать вокруг текущей. По умолчанию `1`.
boundaryCountnumber | undefined1Сколько крайних страниц всегда показывать с каждого края. По умолчанию `1`.
showJumperboolean | undefinedfalseПоказывать поле «перейти к странице» с быстрым переходом по вводу номера.
showPageSizeboolean | undefinedfalseПоказывать селект размера страницы.
showTotalboolean | undefinedfalseПоказывать диапазон показанных элементов — «1–20 из 137». Слот `#total` сильнее.
jumperLabelstring | undefinedundefinedi18n-подпись перед полем перехода. По умолчанию — `gr.pagination.jumpTo`.
pageобязательныйv-modelnumber—Текущая страница с единицы (`v-model:page`). Вне диапазона рисуется прижатой к краю.
pageSizeобязательныйv-modelnumber—Элементов на странице (`v-model:pageSize`) — делитель для числа страниц и диапазона.
totalобязательныйnumber—Сколько элементов всего, а не страниц: число страниц считается из него и `pageSize`.

Слоты

SlotTypeОписание
total{ from: number; to: number; total: number; }Диапазон показанных элементов целиком — вместо строки из локали.

События

EventСигнатураОписание
update:page(event: "update:page", value: number): void—
update:pageSize(event: "update:pageSize", value: number): void—

Типы

Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.

Импорт
import type { GrPaginationPageSizeOption, GrPaginationProps, GrPaginationEmits } from '@feugene/granularity/components/GrPagination'

Файлdist/types/components/GrPagination/GrPagination.vue.d.ts

GrPaginationPageSizeOptiontype

Вариант размера страницы: число либо пара «значение + подпись». Пара нужна там, где подпись не равна числу («50 / стр.», «Все»): собрать её из голого number[] было нельзя, а обходной путь — свой GrSelect рядом — терял связь с пагинацией.

type GrPaginationPageSizeOption = number | {
    value: number;
    label: string;
};
GrPaginationPropsinterface
interface GrPaginationProps {
    /** Текущая страница с единицы (`v-model:page`). Вне диапазона рисуется прижатой к краю. */
    page: number;
    /** Элементов на странице (`v-model:pageSize`) — делитель для числа страниц и диапазона. */
    pageSize: number;
    /** Сколько элементов всего, а не страниц: число страниц считается из него и `pageSize`. */
    total: number;
    /**
     * Варианты размера страницы. Число — подпись равна значению; пара — своя
     * подпись при том же значении («50 / стр.»), которую иначе было не собрать.
     */
    pageSizes?: GrPaginationPageSizeOption[];
    /** Сколько соседних страниц показывать вокруг текущей. По умолчанию `1`. */
    siblingCount?: number;
    /** Сколько крайних страниц всегда показывать с каждого края. По умолчанию `1`. */
    boundaryCount?: number;
    /**
     * Компактный вариант: вместо нумерованных страниц показывается индикатор
     * «текущая / всего» — удобно для узких мест (мобайл, тулбары таблиц).
     */
    compact?: boolean;
    /** Показывать поле «перейти к странице» с быстрым переходом по вводу номера. */
    showJumper?: boolean;
    /** Показывать селект размера страницы. */
    showPageSize?: boolean;
    /** Показывать диапазон показанных элементов — «1–20 из 137». Слот `#total` сильнее. */
    showTotal?: boolean;
    /** i18n-подпись перед полем перехода. По умолчанию — `gr.pagination.jumpTo`. */
    jumperLabel?: string;
    /**
     * Имя навигационного лендмарка. По умолчанию — `gr.pagination.label`; задавать
     * стоит там, где пагинаций на странице несколько и их надо различать.
     */
    ariaLabel?: string;
    /** Гасит всю пагинацию: номера, кнопки, селект размера и поле перехода. */
    disabled?: boolean;
    /**
     * Высота кнопок, поля перехода и селекта по шкале контролов.
     * Не задан — из `GrConfigProvider`, иначе `md`.
     */
    size?: GrPaginationSize;
}
GrPaginationEmitsinterface
interface GrPaginationEmits {
    /**
     * Выбрана страница (`v-model:page`). Приходит и сама, когда `total` или `pageSize`
     * уменьшились и текущая страница оказалась за последней.
     */
    (e: 'update:page', value: number): void;
    /**
     * Выбран размер страницы в селекте (`v-model:pageSize`).
     * На первую страницу компонент не возвращает.
     */
    (e: 'update:pageSize', value: number): void;
}

Файлdist/types/components/GrPagination/config.d.ts

grPaginationConfigconst
const grPaginationConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrPagination">;

Файлdist/types/components/GrPagination/defaults.d.ts

GrPaginationConfigurablePropsinterface

Пропы GrPagination, настраиваемые глобально через componentDefaults.

interface GrPaginationConfigurableProps {
    size: GrComponentSize;
}

Файлdist/types/components/GrPagination/grPaginationStyles.d.ts

GrPaginationSizetype
type GrPaginationSize = GrComponentSize;

Файлdist/types/components/GrPagination/safelist.d.ts

grPaginationSafelistconst
const grPaginationSafelist: string[];

Доступность

Паттерн APG

—

Клавиши

Enter

КлавишаДействие
Enterперейти на введённую страницу

Использование из прозы библиотеки

Контролируемый компонент

page, pageSize и total приходят снаружи, компонент только просит их изменить:

vue
<GrPagination
  v-model:page="page"
  v-model:page-size="pageSize"
  :total="total"
/>

Именно v-model:page, а не v-model: страница — именованная модель, пропа modelValue у компонента нет. Промах видно по атрибуту modelvalue на корневом <div> — необъявленный проп уезжает туда через fallthrough; в dev-режиме компонент дополнительно печатает предупреждение.

Число страниц считается из total и pageSize. Номера усекаются по алгоритму boundary/sibling: всегда видны первая и последняя страницы плюс siblingCount соседей вокруг текущей; boundaryCount задаёт, сколько крайних показывать. Одиночный пропущенный номер рисуется номером, а не многоточием — ряд не прыгает.

Нечисловой вход подменяется дефолтом: не доехавший page даёт первую страницу, total — ноль, pageSize — единицу, и каждый случай объясняется предупреждением в dev-режиме. Без этого undefined разошёлся бы по номерам и статусу как NaN, а разметка осталась бы правдоподобной на вид.

Страница вне диапазона рендерится зажатой к [1, pageCount]: пока родитель не подтянул значение, активная кнопка всё равно есть. Когда число страниц уменьшилось (упал total или вырос pageSize), компонент дополнительно эмитит update:page с последней доступной страницей — если page живёт в URL или сторе, эта навигация произойдёт сама.

Что показывать
ПропЧто добавляет
showPageSizeселект размера страницы; по умолчанию выключен — базовая пагинация это только номера

pageSizes принимает и числа, и пары «значение + подпись»:

vue
<GrPagination :page-sizes="[10, 20, { value: 50, label: '50 / стр.' }]" show-page-size />

Пара нужна там, где подпись не равна числу. Собрать её из голого number[] было нельзя, а обходной путь — свой GrSelect рядом — терял связь с пагинацией. | showTotal | «41–60 из 137» слева от навигации | | showJumper | поле «перейти к странице»: Enter или уход фокуса применяют номер, выходящий за диапазон — клампится | | compact | вместо номеров индикатор «текущая / всего» — для мобайла и тулбаров таблиц |

Диапазон целиком заменяется слотом #total — он получает from, to и total:

vue
<GrPagination :total="total" show-total>
  <template #total="{ from, to, total }">
    Заказы {{ from }}–{{ to }} из {{ total }}
  </template>
</GrPagination>

disabled гасит всё разом: номера, кнопки, селект и поле перехода.

Перенос на узкой ширине

Ряд пагинации — это четыре группы: итог (showTotal), размер страницы (showPageSize), навигация и переход (showJumper). Переносится ряд только между группами. Навигация — первая, назад, страницы, вперёд, последняя — один неразрывный кластер: «назад» не уезжает на другую строку от своих страниц, а на узкой ширине кластер уходит на свою строку целиком и прижимается к концу.

Шире ряда кластер не становится: если не помещается и он один, он прокручивается вбок без видимой полосы. На такой ширине включайте compact — «текущая / всего» вместо номеров — или уменьшайте siblingCount. Ориентиры для siblingCount: 1 (до семи позиций номеров) — ширина кластера с номерами:

sizeкластер
xs≈ 365px
sm≈ 440px
md≈ 525px
lg≈ 595px

С compact кластер при md занимает около 275px.

Сам компонент ширину не меряет: число позиций, зависящее от замера, разошлось бы между сервером и клиентом. Брейкпоинт выбирает раскладка страницы.

Доступность

Корень — role="navigation" с именем из локали (gr.pagination.label). Если пагинаций на странице две (сверху и снизу таблицы), задайте ariaLabel — иначе в обзоре диктора будут два одинаковых лендмарка.

Номера лежат в списке (<ul role="list">), поэтому диктор сообщает их количество; многоточия из него исключены (aria-hidden). Текущая страница помечена aria-current="page".

Смену страницы объявляет живая область: в компактном режиме её несёт видимый индикатор, в обычном — скрытая строка «Страница N из M» (gr.pagination.status).

Размеры

size (xs…lg) читается из GrConfigProvider (componentDefaults.GrPagination.size). Коробка номера — та же высота, что у GrButton того же имени (28/32/40/44): номера и навигационные кнопки стоят в одном ряду, и разойдись шкалы — ряд поедет. Поэтому же sm и md — разные размеры, а не один и тот же рост с разным кеглем.