DataTablePaginator
Visão geral
O componente LxDataTablePaginator oferece controles de navegação para tabelas paginadas. Exibe o seletor de itens por página, o intervalo atual de registros e botões de navegação (primeira, anterior, numeradas, próxima, última).
É totalmente responsivo — em telas menores os elementos menos essenciais são ocultados progressivamente — e acessível, com ARIA labels em todos os controles.
Modos de uso
O LxDataTablePaginator pode ser utilizado de duas formas:
1. Integrado com LxDataTable (Modo Recomendado)
Ideal quando você deseja controlar a paginação de um LxDataTable externamente. Ao usar o slot paginator, o LxDataTable desabilita automaticamente o paginador nativo e usa o LxDataTablePaginator como controlador:
vue
<LxDataTable :value="dadosPaginados">
<!-- Colunas aqui -->
</LxDataTable>
<LxDataTablePaginator
:total-items="totalItems"
:current-page="currentPage"
@update:pagination="handlePaginationUpdate"
/>Ou via slot paginator do LxDataTable:
vue
<LxDataTable :value="dadosPaginados">
<!-- Colunas aqui -->
<template #paginator>
<LxDataTablePaginator
:total-items="totalItems"
:current-page="currentPage"
@update:pagination="handlePaginationUpdate"
/>
</template>
</LxDataTable>2. Isolado (Tabela Manual)
Pode ser utilizado para paginar qualquer tipo de tabela HTML ou lista customizada, sem depender do LxDataTable:
vue
<table>
<!-- Renderizar apenas os dados da página atual -->
</table>
<LxDataTablePaginator
:total-items="totalItems"
:current-page="currentPage"
@update:pagination="handlePaginationUpdate"
/>Exemplo com LxDataTable
Clique para visualizar o código
vue
<script setup>
import { ref, computed } from 'vue';
import { LxDataTable, LxDataTableColumn, LxDataTablePaginator } from '@lde/lxcomponents';
const currentPage = ref(1);
const itemsPerPage = ref(20);
const totalItems = 156;
const statuses = ['Aprovado', 'Pendente', 'Rejeitado', 'Rascunho'];
const categories = ['Eletrônicos', 'Alimentação', 'Vestuário', 'Casa', 'Esportes'];
const allData = Array.from({ length: totalItems }, (_, i) => ({
id: 1000 + i + 1,
produto: `Produto ${String(i + 1).padStart(3, '0')}`,
categoria: categories[i % categories.length],
preco: (i + 1) * 7.5 + 10,
quantidade: ((i * 37) % 500) + 1,
status: statuses[i % statuses.length]
}));
const dadosPaginados = computed(() => {
const start = (currentPage.value - 1) * itemsPerPage.value;
return allData.slice(start, start + itemsPerPage.value);
});
const handlePaginationUpdate = ({ currentPage: page, itemsPerPage: perPage }) => {
currentPage.value = page;
itemsPerPage.value = perPage;
};
const formatCurrency = (value) => {
return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(value);
};
const statusClass = (status) =>
({
Aprovado: 'text-bg-success',
Pendente: 'text-bg-warning',
Rejeitado: 'text-bg-danger',
Rascunho: 'text-bg-secondary'
})[status] ?? 'text-bg-secondary';
</script>
<template>
<div>
<LxDataTable :value="dadosPaginados" data-key="id" :pagination-config="{ paginator: false }">
<LxDataTableColumn field="id" header="ID" header-style="width: 80px" />
<LxDataTableColumn field="produto" header="Produto" />
<LxDataTableColumn field="categoria" header="Categoria" />
<LxDataTableColumn field="preco" header="Preço" header-style="text-align: right">
<template #body="{ data }">
{{ formatCurrency(data.preco) }}
</template>
</LxDataTableColumn>
<LxDataTableColumn field="quantidade" header="Qtd." header-style="text-align: center; width: 80px" />
<LxDataTableColumn field="status" header="Status" header-style="text-align: center; width: 120px">
<template #body="{ data }">
<span class="badge" :class="statusClass(data.status)">{{ data.status }}</span>
</template>
</LxDataTableColumn>
</LxDataTable>
<LxDataTablePaginator
:total-items="totalItems"
:current-page="currentPage"
:items-per-page="itemsPerPage"
:page-options="[10, 20, 50, 100]"
@update:pagination="handlePaginationUpdate"
/>
</div>
</template>Propriedades
| Nome | Descrição | Tipo | Padrão |
|---|---|---|---|
| totalItems | Total de itens a paginar | Number | required |
| currentPage | Página atual (1-indexed) | Number | 1 |
| itemsPerPage | Itens exibidos por página | Number | 10 |
| pageOptions | Opções de itens por página no dropdown | Number[] | [10, 20, 30, 50, 100] |
| disabled | Desabilita toda a navegação | Boolean | false |
| showPageButtons | Exibe botões de páginas numeradas | Boolean | true |
| showLabel | Exibe a label "Mostrar" ao lado do seletor | Boolean | true |
| textAlign | Alinhamento do paginator (left, center, right) | String | 'center' |
| compact | Modo compacto — oculta elementos auxiliares em telas pequenas | Boolean | false |
| size | Tamanho do componente (sm, md, lg) | String | 'md' |
| maxVisiblePages | Número máximo de botões paginados visíveis (deve ser ímpar e ≥ 3) | Number | 5 |
Eventos
| Nome | Descrição | Payload |
|---|---|---|
| update:pagination | Emitido ao mudar de página ou alterar itens por página | { currentPage: number, itemsPerPage: number, totalItems: number } |
Responsividade
| Breakpoint | Comportamento |
|---|---|
> 960px | Exibição completa |
≤ 960px | Oculta a label "Mostrar" e páginas não-adjacentes |
≤ 768px | Oculta também o seletor de itens e o intervalo de página |
altura < 700px | Reduz automaticamente o tamanho dos elementos |
Playground
| Nome | Controle |
|---|---|
Clique para exibir o código
vue
<script setup>
import { reactive, ref } from 'vue';
import { LxDataTablePaginator } from '@lde/lxcomponents';
const paginacao = reactive({
currentPage: 1,
itemsPerPage: 10,
totalItems: 100
});
const props = reactive({
disabled: false,
showPageButtons: true,
showLabel: true,
textAlign: 'center',
compact: false,
size: 'md',
maxVisiblePages: 5
});
const pageOptionsInput = ref('10,20,30,50,100');
const pageOptions = reactive([10, 20, 30, 50, 100]);
const syncPageOptions = () => {
const parsed = pageOptionsInput.value
.split(',')
.map((v) => parseInt(v.trim()))
.filter((v) => !isNaN(v) && v > 0);
pageOptions.splice(0, pageOptions.length, ...parsed);
};
const handlePaginationUpdate = ({ currentPage, itemsPerPage }) => {
paginacao.currentPage = currentPage;
paginacao.itemsPerPage = itemsPerPage;
};
</script>
<template>
<div>
<!-- Resultado -->
<div class="border p-3 rounded mb-3 bg-white">
<LxDataTablePaginator
:total-items="paginacao.totalItems"
:current-page="paginacao.currentPage"
:items-per-page="paginacao.itemsPerPage"
:page-options="pageOptions"
:disabled="props.disabled"
:show-page-buttons="props.showPageButtons"
:show-label="props.showLabel"
:text-align="props.textAlign"
:compact="props.compact"
:size="props.size"
:max-visible-pages="props.maxVisiblePages"
@update:pagination="handlePaginationUpdate"
/>
</div>
<!-- Controles -->
<table>
<thead>
<tr>
<th style="width: 150px">Nome</th>
<th>Controle</th>
</tr>
</thead>
<tbody>
<tr>
<td><label class="form-label m-0">totalItems</label></td>
<td><input v-model.number="paginacao.totalItems" type="number" class="form-control form-control-sm" min="0" /></td>
</tr>
<tr>
<td><label class="form-label m-0">currentPage</label></td>
<td><input v-model.number="paginacao.currentPage" type="number" class="form-control form-control-sm" min="1" /></td>
</tr>
<tr>
<td><label class="form-label m-0">itemsPerPage</label></td>
<td><input v-model.number="paginacao.itemsPerPage" type="number" class="form-control form-control-sm" min="1" /></td>
</tr>
<tr>
<td><label class="form-label m-0">pageOptions</label></td>
<td>
<input v-model="pageOptionsInput" type="text" class="form-control form-control-sm" placeholder="10,20,50" @change="syncPageOptions" />
</td>
</tr>
<tr>
<td><label class="form-label m-0">size</label></td>
<td>
<select v-model="props.size" class="form-select form-select-sm">
<option value="sm">sm</option>
<option value="md">md</option>
<option value="lg">lg</option>
</select>
</td>
</tr>
<tr>
<td><label class="form-label m-0">textAlign</label></td>
<td>
<select v-model="props.textAlign" class="form-select form-select-sm">
<option value="left">left</option>
<option value="center">center</option>
<option value="right">right</option>
</select>
</td>
</tr>
<tr>
<td><label class="form-label m-0">maxVisiblePages</label></td>
<td>
<select v-model.number="props.maxVisiblePages" class="form-select form-select-sm">
<option :value="3">3</option>
<option :value="5">5</option>
<option :value="7">7</option>
<option :value="9">9</option>
</select>
</td>
</tr>
<tr>
<td><label class="form-label m-0">disabled</label></td>
<td><input v-model="props.disabled" class="form-check-input" type="checkbox" /></td>
</tr>
<tr>
<td><label class="form-label m-0">showLabel</label></td>
<td><input v-model="props.showLabel" class="form-check-input" type="checkbox" /></td>
</tr>
<tr>
<td><label class="form-label m-0">showPageButtons</label></td>
<td><input v-model="props.showPageButtons" class="form-check-input" type="checkbox" /></td>
</tr>
<tr>
<td><label class="form-label m-0">compact</label></td>
<td><input v-model="props.compact" class="form-check-input" type="checkbox" /></td>
</tr>
</tbody>
</table>
</div>
</template>
LxComponents