VxTable
Sistema de tabela customizado com 5 sub-componentes. Estende o vs-table do Vuesax com ordenação por coluna,
seleção simples/múltipla, paginação (client-side e server-side), busca integrada, linhas expansíveis e edição inline.
Não usa vs-table internamente — reimplementa do zero com lógica própria.
vs-th/vs-tr/vs-td
(Vuesax) como filhos de vx-table — nunca vx-th/vx-tr/vx-td (custom).
Os sub-componentes custom são necessários apenas para linhas expansíveis e edição inline.
Padrão Admin (search + pagination + toolbar)
Padrão universal nos 18 usos reais. Toolbar no slot header: botão "Adicionar Novo" + dropdown de itens por página.
Headers com sort-key. Slot escopado slot-scope="{data}" com vs-tr/vs-td Vuesax.
| Nome | Status | Ações |
|---|---|---|
Suporte Técnico |
Ativo |
|
Vendas |
Ativo |
|
Financeiro |
Inativo |
|
<vx-table
ref="table"
noDataText="Sem dados disponíveis"
pagination
:max-items="itemsPerPage"
search
:data="userDepartments"
>
<!-- Toolbar no slot header -->
<div slot="header" class="flex flex-wrap-reverse items-center flex-grow justify-between">
<div class="p-3 mb-4 rounded-lg cursor-pointer flex items-center
text-base text-primary border border-solid border-primary"
@click="addNewData"
>
<feather-icon icon="PlusIcon" svgClasses="h-4 w-4" />
<span class="ml-2">Adicionar Novo</span>
</div>
<vs-dropdown vs-trigger-click class="cursor-pointer mb-4">
<div class="p-4 border border-solid rounded-full flex items-center font-medium">
<span class="mr-2">{{ currentPage * itemsPerPage - (itemsPerPage - 1) }} - {{ ... }} de {{ queriedItems }}</span>
<feather-icon icon="ChevronDownIcon" svgClasses="h-4 w-4" />
</div>
<vs-dropdown-menu>
<vs-dropdown-item @click="itemsPerPage = 10">10</vs-dropdown-item>
<vs-dropdown-item @click="itemsPerPage = 20">20</vs-dropdown-item>
</vs-dropdown-menu>
</vs-dropdown>
</div>
<!-- Cabeçalho com vs-th (Vuesax) -->
<template slot="thead">
<vs-th sort-key="name">Nome</vs-th>
<vs-th sort-key="activated">Status</vs-th>
<vs-th>Ações</vs-th>
</template>
<!-- Linhas com vs-tr/vs-td (Vuesax) -->
<template slot-scope="{data}">
<tbody>
<vs-tr :data="tr" :key="indextr" v-for="(tr, indextr) in data">
<vs-td><p class="font-medium truncate">{{ tr.name }}</p></vs-td>
<vs-td>
<vs-chip :color="getStatusColor(tr.activated)">
{{ tr.activated ? 'Ativo' : 'Inativo' }}
</vs-chip>
</vs-td>
<vs-td class="whitespace-no-wrap">
<feather-icon icon="EditIcon" svgClasses="w-5 h-5 hover:text-primary" @click.stop="editData(tr)" />
<feather-icon icon="TrashIcon" svgClasses="w-5 h-5 hover:text-danger" @click.stop="deleteData(tr)" />
</vs-td>
</vs-tr>
</tbody>
</template>
</vx-table>
Estados de Linha + Stripe
vs-tr :state="'success|danger|warning'" aplica cor de fundo na linha.
stripe alterna fundo em linhas pares. Nenhum dos dois foi encontrado nos 18 usos reais.
| Pedido | Status | Valor |
|---|---|---|
| #1001 | Entregue | R$ 149,90 |
| #1002 | Em rota | R$ 89,50 |
| #1003 | Atrasado | R$ 210,00 |
| #1004 | Entregue | R$ 55,00 |
<vx-table :data="orders" noDataText="Sem pedidos">
<template slot-scope="{data}">
<tbody>
<vs-tr
:data="tr" :key="i" v-for="(tr, i) in data"
:state="tr.status === 'atrasado' ? 'danger'
: tr.status === 'entregue' ? 'success'
: tr.status === 'em_rota' ? 'warning'
: null"
>
<vs-td>{{ tr.id }}</vs-td>
<vs-td>{{ tr.status }}</vs-td>
</vs-tr>
</tbody>
</template>
</vx-table>
Linhas Expansíveis
Requer vx-tr (custom) com slot expand. Seta aparece na primeira célula.
Ao clicar, um painel full-width abre abaixo via Vue.extend(VxTrExpand) — instanciação programática.
Não encontrado nos 18 usos reais do admin.
| Nome | Telefone |
|---|---|
| Maria Silva | (11) 98765-4321 |
| João Santos | (21) 99876-5432 |
<!-- NOTA: requer vx-tr (custom), não vs-tr (Vuesax) -->
<vx-table :data="contacts" noDataText="Sem contatos">
<template slot="thead">
<vx-th sort-key="name">Nome</vx-th>
<vx-th sort-key="phone">Telefone</vx-th>
</template>
<template slot-scope="{data}">
<tbody>
<vx-tr :data="tr" :key="i" v-for="(tr, i) in data">
<vx-td>{{ tr.name }}</vx-td>
<vx-td>{{ tr.phone }}</vx-td>
<template slot="expand">
<div class="p-4">
<p>Email: {{ tr.email }}</p>
<p>Endereço: {{ tr.address }}</p>
</div>
</template>
</vx-tr>
</tbody>
</template>
</vx-table>
Server-Side (sst)
sst=true desativa filtragem/paginação/ordenação client-side.
Os eventos @search, @change-page e @sort são emitidos
para o pai fazer as chamadas ao servidor. :total informa o total de registros.
@search="handleSearch" — texto digitado no campo de busca
@change-page="handleChangePage" — número da página selecionada
@sort="handleSort" — { key: String, sortType: 'asc'|'desc'|null }
<vx-table
:sst="true"
:data="users"
:total="totalUsers"
pagination
search
max-items="20"
v-model="selected"
@search="handleSearch"
@change-page="handleChangePage"
@sort="handleSort"
>
<template slot="thead">
<vs-th sort-key="name">Nome</vs-th>
<vs-th sort-key="email">Email</vs-th>
<vs-th sort-key="created_at">Criado em</vs-th>
</template>
<template slot-scope="{data}">
<tbody>
<vs-tr :data="tr" :key="indextr" v-for="(tr, indextr) in data">
<vs-td>{{ tr.name }}</vs-td>
<vs-td>{{ tr.email }}</vs-td>
<vs-td>{{ tr.created_at | formatDate }}</vs-td>
</vs-tr>
</tbody>
</template>
</vx-table>
API
Sub-componentes
| Componente | Descrição | Uso no admin |
|---|---|---|
VxTable | Container. Gerencia dados, paginação, busca, seleção. | Sempre |
VxTh | Header de coluna com sort. Comunica via $parent. | Sintético — admin usa vs-th |
VxTd | Célula com slot edit para edição inline. | Sintético — admin usa vs-td |
VxTr | Linha com estado de cor e slot expand. | Sintético — admin usa vs-tr |
VxTrExpand | Linha expandida. Instanciada via Vue.extend — não usada diretamente. | Interno |
Props — VxTable (principais)
| Nome | Tipo | Default | Descrição |
|---|---|---|---|
data | Array | — | Array de objetos. Obrigatório. Usado para paginação/busca/ordenação client-side. |
v-model (value) | Any | — | Seleção. Array para multiple=true, objeto para simples. |
pagination | Boolean | false | Ativa paginação com vs-pagination no rodapé. |
maxItems | Number|String | 5 | Itens por página. |
search | Boolean | false | Campo de busca no header. Filtra client-side por todos os campos. |
multiple | Boolean | false | Checkboxes para seleção múltipla. |
stripe | Boolean | false | Linhas alternadas. Não usado no admin real. |
maxHeight | String | "auto" | Altura máxima do tbody + scroll interno. |
sst | Boolean | false | Server-side: busca/paginação/sort emitem eventos ao invés de filtrar. |
total | Number | 0 | Total de registros para cálculo de páginas no modo SST. |
noDataText | String | "No data Available" | Texto quando sem dados. Mudar para PT-BR nos usos. |
Slots — VxTable
| Slot | Escopado | Descrição |
|---|---|---|
header | Não | Toolbar: botões de ação, dropdown de itens/página, filtros extras. |
thead | Não | Conteúdo do header (vs-th ou vx-th). Dentro do tr do thead. |
default (slot-scope) | Sim — {data} | Linhas (vs-tr ou vx-tr). data é o array já paginado/filtrado. |
Eventos — VxTable
| Evento | Payload | Quando |
|---|---|---|
@input (v-model) | Object|Array | Linha selecionada |
@selected | Object | Click numa linha |
@dblSelection | Object | Double-click numa linha |
@change-page | Number | Mudança de página (SST) |
@search | String | Busca digitada (SST) |
@sort | (key, sortType) | Header clicado (SST) |
Onde é usado (principais)
| Arquivo | Nota |
|---|---|
src/views/messages/MessageTemplate.vue | Templates de mensagem |
src/views/user-departments/UserDepartmentsList.vue | Departamentos de usuário |
src/views/roles/RolesList.vue | Listagem de perfis |
src/views/roles/TableRoles.vue | Tabela de roles |
src/views/user-departments/UserDepartmentsSlimList.vue | Lista reduzida de departamentos |