Documentos PDF
mad-doc-data-table
mad-doc-data-table-column
mad-doc-repeater
Tabela de dados
mad-doc-data-table + mad-doc-data-table-column lendo TutorDemoPedido, agrupado por categoria.
Pedidos recentes por categoria
| Cód. | Cliente | Data | Valor |
|---|---|---|---|
| ▸ Brinquedos | |||
| 128 | Rafael Pereira | 28/09/2026 | 6.685,43 |
| 55 | Ana Souza | 11/09/2026 | 4.464,35 |
| 11.149,78 | |||
| ▸ Eletrônicos | |||
| 99 | Rafael Pereira | 24/09/2026 | 5.963,62 |
| 84 | Gabriela Pereira | 18/09/2026 | 7.745,58 |
| 141 | Hugo Almeida | 09/09/2026 | 5.400,52 |
| 64 | Nelson Araújo | 06/09/2026 | 846,66 |
| 19.956,38 | |||
| ▸ Vestuário | |||
| 18 | Fábio Souza | 16/09/2026 | 703,92 |
| 27 | Mariana Almeida | 06/09/2026 | 5.617,90 |
| 117 | Isabela Araújo | 03/09/2026 | 807,20 |
| 7.129,02 | |||
| ▸ Móveis | |||
| 108 | Nelson Araújo | 14/09/2026 | 2.321,95 |
| 2.321,95 | |||
| ▸ Alimentos | |||
| 63 | Karina Souza | 11/09/2026 | 7.133,89 |
| 36 | Diego Araújo | 02/09/2026 | 5.981,71 |
| 13.115,60 | |||
| 53.672,73 | |||
TOTAL GERAL: 53.672,73
resources/views/tutor/examples/pdf-tabelas/tabela-pedidos.blade.php
@php
$totalsPedidos = $totalsPedidos ?? new \ArrayObject();
@endphp
<mad-doc-heading :level="2">Pedidos recentes por categoria</mad-doc-heading>
<mad-doc-data-table model="TutorDemoPedido"
:filter="fn($q) => $q->orderByDesc('dt_pedido')->limit(12)"
:totals="$totalsPedidos" group-by="categoria.nome"
header-bg="#eef2ff" :zebra="true" :font-size="9">
<mad-doc-data-table-column label="Cód." field="id" align="center" width="50px" />
<mad-doc-data-table-column label="Cliente" field="cliente.nome" align="left" />
<mad-doc-data-table-column label="Data" field="dt_pedido" align="center" formatter="date" width="80px" />
<mad-doc-data-table-column label="Valor" field="valor_total" align="right" formatter="money"
total="sum" total-name="valor_geral" width="100px" />
</mad-doc-data-table>
<mad-doc-variable-field :value="$totalsPedidos['valor_geral'] ?? 'R$ 0,00'"
prefix="TOTAL GERAL: " align="right" :size="12" :bold="true" />
Repetidor (layout livre)
mad-doc-repeater percorre os itens de um pedido com agregados (:aggregates).
Itens do pedido "Pedido #144"
| Item avulso | 8x | R$ 4.240,64 |
| Item avulso | 6x | R$ 4.293,54 |
| Unidade padrão | 6x | R$ 3.784,62 |
| Combo promocional | 6x | R$ 2.283,18 |
Total: 14.601,98 (26 un.)
resources/views/tutor/examples/pdf-tabelas/repeater-itens.blade.php
@php
// Dois chamadores possíveis:
// - preview ao vivo (<x-tutor-demo>, escopo isolado): $pedidoDemo não
// existe ainda — busca no host via MadRenderContext (método público,
// NUNCA @php com query Eloquent direto no blade).
// - geração do PDF (TutorPdfTabelas::gerarPdf, chamado no mount() —
// ANTES de MadComponent::render() empurrar o contexto): o controller
// já passa $pedidoDemo pronto pro MadBlade::render().
$pedidoDemo = $pedidoDemo ?? \Mad\Component\MadRenderContext::getComponent()?->pedidoDemo();
$tutorRepeaterEmpty = '<p style="text-align:center;color:#94a3b8;">Sem itens.</p>';
@endphp
<mad-doc-heading :level="2">Itens do pedido "{{ $pedidoDemo->descricao }}"</mad-doc-heading>
<mad-doc-repeater :rows="$pedidoDemo->itens"
:aggregates="[
'qtd_total' => ['op' => 'sum', 'field' => 'qtd', 'format' => 'integer'],
'valor_total_itens' => ['op' => 'sum', 'field' => 'total', 'format' => 'money'],
]"
:empty="$tutorRepeaterEmpty">
<table style="width:100%;border-collapse:collapse;margin:2pt 0;font-size:9pt;">
<tr>
<td style="width:60%;"><strong>{{ $record->descricao }}</strong></td>
<td style="width:15%;text-align:right;">{{ (int) $record->qtd }}x</td>
<td style="width:25%;text-align:right;">R$ {{ number_format((float) $record->total, 2, ',', '.') }}</td>
</tr>
</table>
</mad-doc-repeater>
<mad-doc-text align="right" :size="11">
<strong>Total: {{ $totals['valor_total_itens'] ?? '' }} ({{ $totals['qtd_total'] ?? 0 }} un.)</strong>
</mad-doc-text>
Código-fonte completo da página
app/control/Tutor/TutorPdfTabelas.php
<?php
namespace App\Control\Tutor;
use App\Models\TutorDemo\TutorDemoPedido;
use App\Support\Tutor\TutorDemoSeed;
use App\Support\Tutor\TutorPage;
use Mad\Doc\MadDocPdf;
use Mad\Service\MadUploadStorage;
use Mad\View\MadBlade;
/**
* TutorPdfTabelas — tabelas em PDF: mad-doc-data-table, mad-doc-data-table-column,
* mad-doc-repeater.
*
* Ao contrário de pdf_basico, nenhuma tag desta página é incompatível com o
* preview ao vivo (sem <mad-doc-page>, sem position:fixed) — os parciais
* "ao vivo" são exatamente os mesmos incluídos no wrapper -doc.blade.php
* usado pra gerar o PDF (ver TutorPdfBasico pro caso onde isso NÃO vale).
*/
class TutorPdfTabelas extends TutorPage
{
protected string $catalogKey = 'pdf_tabelas';
private const EXEMPLOS = ['tabela-pedidos', 'repeater-itens'];
/** exemplo => URL assinada do PDF já gerado (mad.download). */
public array $pdfUrls = [];
public function mount(array $params = []): void
{
TutorDemoSeed::ensure();
foreach (self::EXEMPLOS as $exemplo) {
$this->pdfUrls[$exemplo] = $this->gerarPdf($exemplo);
}
}
/** Pedido fixo (o de maior valor) usado pelo exemplo de repeater — dados reais da fixture. */
public function pedidoDemo(): TutorDemoPedido
{
return TutorDemoPedido::query()
->with('itens')
->orderByDesc('valor_total')
->firstOrFail();
}
private function gerarPdf(string $exemplo): string
{
// O exemplo "repeater-itens" lê $pedidoDemo via MadRenderContext no
// preview ao vivo (host = esta página, contexto empurrado por
// MadComponent::render()) — mas aqui em mount() esse contexto ainda
// não existe (render() só empurra DEPOIS do mount). Passamos o dado
// direto pro MadBlade::render(); @include sem array herda o escopo
// do pai, então $pedidoDemo chega intacto no parcial.
$data = $exemplo === 'repeater-itens' ? ['pedidoDemo' => $this->pedidoDemo()] : [];
$html = MadBlade::render('tutor.examples.pdf-tabelas.' . $exemplo . '-doc', $data);
$pdf = MadDocPdf::fromHtml($html);
$path = 'tutor-pdf/pdf-tabelas/' . $exemplo . '.pdf';
MadUploadStorage::putContent($path, $pdf);
return mad_download_url($path);
}
}
resources/views/tutor/pdf/tabelas.blade.php
<x-tutor-page page="pdf_tabelas">
<x-tutor-demo demo="tutor.examples.pdf-tabelas.tabela-pedidos"
title="Tabela de dados" desc="mad-doc-data-table + mad-doc-data-table-column lendo TutorDemoPedido, agrupado por categoria." />
<div style="margin:8px 0 24px;">
<mad-btn variant="primary" icon="file-text" :href="$pdfUrls['tabela-pedidos']"
attrs='target="_blank" rel="noopener"'>Ver PDF</mad-btn>
</div>
<x-tutor-demo demo="tutor.examples.pdf-tabelas.repeater-itens"
title="Repetidor (layout livre)" desc="mad-doc-repeater percorre os itens de um pedido com agregados (:aggregates)." />
<div style="margin:8px 0 24px;">
<mad-btn variant="primary" icon="file-text" :href="$pdfUrls['repeater-itens']"
attrs='target="_blank" rel="noopener"'>Ver PDF</mad-btn>
</div>
</x-tutor-page>