mad-pivot-table
Tabela dinâmica/cross-tab (React/iframe).
Tabela dinamica (pivot/cross-tab) com agrupamento por linhas, colunas, agregacao de valores e filtros interativos. Auto-query via ORM ou dados manuais. Renderizada num iframe React (manager.madbuilder.com.br/mad-table) — zero codigo no controller.
Tag compilada pelo MadGridCompiler.
Nota: as tags filhas
<mad-pivot-row>,<mad-pivot-col>,<mad-pivot-value>e<mad-pivot-filter>NAO sao components Blade autonomos — so existem como sintaxe dentro de<mad-pivot-table>. OMadGridCompiler(packages/mad-framework/src/mad/grid/MadGridCompiler.php) faz regex nessas tags e transforma tudo num array$pivot_fieldspassado para<x-pivot-table :pivot_fields="...">(pivot-table.blade.php). Usa-las fora do<mad-pivot-table>ou tentar renderiza-las isoladamente nao funciona.
Estrutura basica
<mad-pivot-table model="DocPivotVenda" database="minierp"
title="Vendas por Regiao" height="500">
<mad-pivot-row field="regiao" label="Regiao" />
<mad-pivot-value field="valor" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Props do <mad-pivot-table>
| Prop | Tipo | Default | Descricao |
|---|---|---|---|
| model | string | '' | Classe do model Eloquent para auto-query (ex: PedidoVenda) |
| database | string | MAIN_DATABASE | Conexao do banco |
| filters | array | [] | Filtros inline: [['campo', 'op', 'val'], ...] |
| joins | array | [] | Joins keyed por tabela: ['tabela' => ['fk', 'pk']] ou ['tabela' => ['fk', 'op', 'pk']]. Ex: ['vendedor' => ['pedido_venda.vendedor_id', 'vendedor.id']]. A PK precisa de prefixo explícito (tabela.pk) — sem ., o parser qualifica na tabela base. |
| data | array | null | Dados manuais (dispensa model) |
| transformers | array | [] | Map ['campo' => callable] para transformar valores |
| title | string | '' | Titulo do card |
| subtitle | string | '' | Subtitulo |
| height | int/string | 600 | Altura em px ou string com unidade |
| width | string | '100%' | Largura |
| no-panel | bool | false | Sem card wrapper |
| no-data-label | string | 'Sem dados para exibir' | Texto quando vazio |
| field-list | bool | false | Mostra lista drag-and-drop |
| field-list-layout | string | 'horizontal' | horizontal, vertical-left, vertical-right |
| virtual-scrolling | bool | true | Scroll virtual para grandes datasets |
| rows-per-page | int | 50 | Linhas por pagina |
| subtotals | bool | false | Habilita subtotais por grupo |
| subtotals-position | string | 'below' | above, below |
| grand-totals | bool | true | Habilita totais gerais |
| row-totals | bool | true | Totais de linha |
| column-totals | bool | true | Totais de coluna |
| language | string | 'pt-BR' | pt-BR, en, es |
| currency | string | 'BRL' | Moeda padrao (ISO 4217) |
| locale | string | 'pt-BR' | Locale padrao |
| theme | string | '' | default, dark, compact |
| compact | bool | false | Modo compacto |
| presets | array | [] | Presets de configuracao salvos |
| class | string | '' | Classes CSS extras |
Tags filhas
| Tag | Area | Uso |
|---|---|---|
<mad-pivot-row> |
rows | Campo de agrupamento por linha |
<mad-pivot-col> |
columns | Campo de agrupamento por coluna (cross-tab) |
<mad-pivot-value> |
values | Campo agregado (sum, avg, count, etc) |
<mad-pivot-filter> |
filters | Campo de filtro interativo |
A ordem de declaracao de cada area define a hierarquia (ex: dois <mad-pivot-row> criam dois niveis de agrupamento).
Props comuns (row, col, filter)
| Prop | Tipo | Default | Descricao |
|---|---|---|---|
| field | string | '' | Nome da coluna no model (obrigatorio) |
| label | string | field | Label exibido |
| type | string | 'string' | string, number, date |
| date-format | string | '' | Formato quando type=date |
| locale | string | locale do pai | Locale customizado |
Props de <mad-pivot-value>
| Prop | Tipo | Default | Descricao |
|---|---|---|---|
| field | string | '' | Coluna do model (obrigatorio) |
| label | string | field | Label exibido |
| type | string | 'number' | number, string |
| aggregation | string | 'sum' | sum, avg, count, min, max, countDistinct |
| format | string | 'number' | number, currency, percent, string |
| currency | string | currency do pai | Moeda (quando format=currency) |
| locale | string | locale do pai | Locale customizado |
Exemplo 1 — Basico (uma linha, um valor)
<mad-pivot-table model="PedidoVenda" database="minierp"
title="Vendas por Regiao" height="500">
<mad-pivot-row field="regiao" label="Regiao" />
<mad-pivot-value field="valor" label="Valor Total"
aggregation="sum" format="currency" currency="BRL" />
<mad-pivot-value field="quantidade" label="Quantidade"
aggregation="sum" format="number" />
</mad-pivot-table>
Exemplo 2 — Cross-tab (regiao x categoria)
<mad-pivot-table model="PedidoVenda" database="minierp"
title="Vendas: Regiao x Categoria" height="500">
<mad-pivot-row field="regiao" label="Regiao" />
<mad-pivot-col field="categoria" label="Categoria" />
<mad-pivot-value field="valor" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Exemplo 3 — Multi-nivel com subtotais
<mad-pivot-table model="PedidoVenda" database="minierp"
title="Vendas por Regiao e Estado" height="550" subtotals>
<mad-pivot-row field="regiao" label="Regiao" />
<mad-pivot-row field="estado" label="Estado" />
<mad-pivot-value field="valor" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
<mad-pivot-value field="lucro" label="Lucro"
aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Exemplo 4 — Multiplas agregacoes do mesmo campo
<mad-pivot-table model="PedidoVenda" database="minierp"
title="Analise por Categoria" height="500">
<mad-pivot-row field="categoria" label="Categoria" />
<mad-pivot-value field="valor" label="Total Vendas"
aggregation="sum" format="currency" currency="BRL" />
<mad-pivot-value field="valor" label="Ticket Medio"
aggregation="avg" format="currency" currency="BRL" />
<mad-pivot-value field="id" label="Num. Vendas"
aggregation="count" format="number" />
</mad-pivot-table>
Exemplo 5 — Com filtros interativos
<mad-pivot-table model="PedidoVenda" database="minierp"
title="Vendas por Vendedor e Canal" height="500">
<mad-pivot-row field="vendedor" label="Vendedor" />
<mad-pivot-col field="canal" label="Canal de Venda" />
<mad-pivot-value field="valor" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
<mad-pivot-filter field="regiao" label="Regiao" />
<mad-pivot-filter field="categoria" label="Categoria" />
</mad-pivot-table>
Exemplo 6 — Field list drag-and-drop
Permite ao usuario arrastar campos entre areas (rows, columns, values, filters) interativamente.
<mad-pivot-table model="PedidoVenda" database="minierp"
title="Pivot Interativo" height="600" field-list>
<mad-pivot-row field="regiao" label="Regiao" />
<mad-pivot-row field="categoria" label="Categoria" />
<mad-pivot-col field="mes" label="Mes" />
<mad-pivot-value field="valor" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
<mad-pivot-filter field="vendedor" label="Vendedor" />
</mad-pivot-table>
Exemplo 7 — Dados manuais (sem model)
@php
$vendas = [
['produto' => 'Notebook', 'trimestre' => 'Q1', 'vendas' => 15000, 'unidades' => 12],
['produto' => 'Notebook', 'trimestre' => 'Q2', 'vendas' => 18500, 'unidades' => 15],
['produto' => 'Monitor', 'trimestre' => 'Q1', 'vendas' => 8200, 'unidades' => 20],
['produto' => 'Monitor', 'trimestre' => 'Q2', 'vendas' => 9100, 'unidades' => 22],
];
@endphp
<mad-pivot-table :data="$vendas" title="Vendas por Produto" height="400">
<mad-pivot-row field="produto" label="Produto" />
<mad-pivot-col field="trimestre" label="Trimestre" />
<mad-pivot-value field="vendas" label="Vendas"
aggregation="sum" format="currency" currency="BRL" />
<mad-pivot-value field="unidades" label="Unidades"
aggregation="sum" format="number" />
</mad-pivot-table>
Exemplo 8 — Com filtros inline
<mad-pivot-table model="PedidoVenda" database="minierp"
:filters="[['regiao', 'in', \"('Sul', 'Sudeste')\"]]"
title="Vendas — Sul e Sudeste" height="450">
<mad-pivot-row field="estado" label="Estado" />
<mad-pivot-col field="categoria" label="Categoria" />
<mad-pivot-value field="valor" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Exemplo 9 — Filtros montados dinamicamente
@php
$filtros = [
['ano', '=', date('Y')],
['ativo', '=', '1'],
];
@endphp
<mad-pivot-table model="PedidoVenda" :filters="$filtros"
title="Vendas do Ano Atual" height="500">
<mad-pivot-row field="mes" label="Mes" />
<mad-pivot-value field="valor" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Exemplo 10 — Sem panel (bare)
<mad-pivot-table model="PedidoVenda" database="minierp"
title="Vendas" height="400" no-panel>
<mad-pivot-row field="categoria" label="Categoria" />
<mad-pivot-value field="valor" label="Valor"
aggregation="sum" format="currency" currency="BRL" />
</mad-pivot-table>
Avancado — multiplas views salvas (<mad-pivot-field> + <mad-pivot-view>)
Alem da sintaxe direta (<mad-pivot-row|col|value|filter>, mantida por
retrocompat e suficiente pra 90% dos casos), o MadGridCompiler tambem aceita
um schema de catalogo de campos + views nomeadas: declare os campos uma
vez com <mad-pivot-field> (a area default vem de area="rows|columns|values|filters")
e agrupe combinacoes diferentes em blocos <mad-pivot-view> — cada view vira
um preset que o usuario troca pelo seletor da UI sem reconfigurar nada.
<mad-pivot-table model="PedidoVenda" database="minierp"
title="Vendas" height="550" field-list>
<mad-pivot-field field="regiao" label="Regiao" area="rows" />
<mad-pivot-field field="categoria" label="Categoria" area="columns" />
<mad-pivot-field field="vendedor" label="Vendedor" area="rows" />
<mad-pivot-field field="valor" label="Valor" area="values"
aggregation="sum" format="currency" currency="BRL" />
<mad-pivot-view name="Por regiao" default>
<mad-pivot-row field="regiao" />
<mad-pivot-col field="categoria" />
<mad-pivot-value field="valor" />
</mad-pivot-view>
<mad-pivot-view name="Por vendedor">
<mad-pivot-row field="vendedor" />
<mad-pivot-value field="valor" />
</mad-pivot-view>
</mad-pivot-table>
Dentro de <mad-pivot-view>, os sub-tags row/col/value/filter apenas
referenciam o field pelo nome (a definicao completa — type, aggregation,
format — fica no <mad-pivot-field> do catalogo); a area e a ordem vêm de
onde o field aparece dentro da view. A view marcada default é a que abre
inicialmente; as demais ficam disponíveis num seletor de presets na UI. Use
isso quando a mesma tabela precisa de 2+ recortes que o usuário troca sem
reabrir o editor de campos (field-list).
Agregacoes disponiveis
| Valor | Descricao |
|---|---|
sum |
Soma |
avg |
Media |
count |
Contagem |
min |
Minimo |
max |
Maximo |
countDistinct |
Contagem distinta |
Formatos de valor
| Valor | Descricao |
|---|---|
number |
Numero decimal |
currency |
Moeda (usa currency e locale) |
percent |
Porcentagem |
string |
Texto |
NUNCA fazer
{{-- ERRADO: montar pivot manualmente com @foreach aninhado --}}
@foreach($regioes as $r)
<tr>
<td>{{ $r }}</td>
@foreach($categorias as $c)
<td>{{ $totais[$r][$c] ?? 0 }}</td>
@endforeach
</tr>
@endforeach
{{-- CERTO --}}
<mad-pivot-table model="PedidoVenda">
<mad-pivot-row field="regiao" label="Regiao" />
<mad-pivot-col field="categoria" label="Categoria" />
<mad-pivot-value field="valor" aggregation="sum" format="currency" />
</mad-pivot-table>
{{-- ERRADO: usar BMadTable do builder no controller --}}
$pivot = new BMadTable();
$pivot->setModel('PedidoVenda');
$pivot->addField(...);
{{-- CERTO: declarativo no Blade --}}
<mad-pivot-table model="PedidoVenda">...</mad-pivot-table>
{{-- ERRADO: query manual + array_reduce no controller para depois passar pro Blade --}}
$dados = PedidoVenda::where('ano', '=', date('Y'))->get();
$pivot = [];
foreach ($dados as $d) { $pivot[$d->regiao][$d->categoria] += $d->valor; }
return ['view', ['pivot' => $pivot]];
{{-- CERTO: o componente faz a query automaticamente --}}
<mad-pivot-table model="PedidoVenda" :filters="[['ano','=',date('Y')]]">...</mad-pivot-table>
{{-- ERRADO: declarar pivot-row sem field --}}
<mad-pivot-row label="Regiao" />
{{-- CERTO: field e obrigatorio --}}
<mad-pivot-row field="regiao" label="Regiao" />
{{-- ERRADO: pivot-value sem aggregation explicito quando precisa de outro alem de sum --}}
<mad-pivot-value field="valor" label="Media" format="currency" />
{{-- → vai usar sum por default, nao avg --}}
{{-- CERTO --}}
<mad-pivot-value field="valor" label="Media" aggregation="avg" format="currency" currency="BRL" />
{{-- ERRADO: usar mad-grid para tentar fazer cross-tab --}}
<mad-grid self>
<mad-columns>
<mad-col field="regiao" />
<mad-col field="categoria" />
<mad-col field="valor" total="sum" />
</mad-columns>
</mad-grid>
{{-- CERTO: mad-grid e listagem; cross-tab e mad-pivot-table --}}
<mad-pivot-table model="PedidoVenda">
<mad-pivot-row field="regiao" />
<mad-pivot-col field="categoria" />
<mad-pivot-value field="valor" aggregation="sum" format="currency" />
</mad-pivot-table>