Listagens e tabelas
mad-act
mad-action
mad-actions
mad-action-group
mad-del
mad-nav
mad-seek
Navegação de exemplo
O
<mad-nav> abaixo aponta para a página Texto
(Formulários) só pra ilustrar a navegação — o Tutor não tem uma tela de
"detalhe do pedido" dedicada. Numa tela real o target seria o
form/detalhe do próprio registro (ex.: PedidoForm::onEdit({id})).
Navegar (mad-nav)
mad-nav abre outra tela — nunca mad-act pra isso.
Visible columns
|
Cod.
|
Descrição
|
Cliente
|
|
|---|---|---|---|
| 1 | Pedido #1 |
|
|
| 2 | Pedido #2 |
|
|
| 3 | Pedido #3 |
|
|
| 4 | Pedido #4 |
|
|
| 5 | Pedido #5 |
|
|
| 6 | Pedido #6 |
|
|
| 7 | Pedido #7 |
|
|
| 8 | Pedido #8 |
|
resources/views/tutor/examples/grids-acoes/navegar.blade.php
<mad-grid model="TutorDemoPedido" per-page="8">
<mad-columns>
<mad-col field="id" label="Cod." width="70" sort />
<mad-col field="descricao" label="Descrição" />
<mad-col field="{cliente->nome}" label="Cliente" />
</mad-columns>
<mad-actions>
<mad-nav icon="eye" label="Ver exemplo" target="TutorFormsTexto" />
</mad-actions>
</mad-grid>
Ações completas
mad-act, mad-action (alias), mad-action-group, mad-del, when-field e display-condition no mesmo grid.
Visible columns
|
Cod.
|
Descrição
|
Cliente
|
Estado
|
Valor
|
|
|---|---|---|---|---|---|
|
|
150 | Pedido #150 | Carla Almeida | Entregue | R$ 4.095,50 |
|
|
149 | Pedido #149 | Patrícia Souza | Enviado | R$ 1.516,96 |
|
|
148 | Pedido #148 | Sabrina Almeida | Cancelado | R$ 10.132,22 |
|
|
147 | Pedido #147 | Karina Souza | Entregue | R$ 5.723,62 |
|
|
146 | Pedido #146 | Rafael Pereira | Enviado | R$ 7.613,07 |
|
|
145 | Pedido #145 | Patrícia Souza | Novo | R$ 9.130,34 |
|
|
144 | Pedido #144 | Lucas Pereira | Entregue | R$ 14.601,98 |
|
|
143 | Pedido #143 | Rafael Pereira | Enviado | R$ 4.745,48 |
resources/views/tutor/examples/grids-acoes/completas.blade.php
@php
// O grid "self" desta pagina compila pra uma chamada em cima da variavel
// LEXICAL $__component. Este partial e incluido de dentro do componente
// Blade nativo tutor-demo (escopo isolado), entao $__component nao chega
// ate aqui sozinho. MadRenderContext::getComponent() le o MESMO dado via
// stack estatico (push/pop em MadComponent::render()), que atravessa
// esse aninhamento. NUNCA escreva o texto literal da tag grid+self dentro
// de um comentario neste arquivo: o compilador de tags do MAD e
// regex-based e nao entende comentario PHP — ele casaria a abertura da
// tag aqui no comentario com o FECHAMENTO real la embaixo, e tudo no meio
// vira corpo do bloco errado (bug real, ja pego em produção neste lote).
$__component = \Mad\Component\MadRenderContext::getComponent();
@endphp
<mad-grid self per-page="8">
<mad-columns>
<mad-col field="id" label="Cod." width="70" center sort />
<mad-col field="descricao" label="Descrição" sort />
<mad-col field="{cliente->nome}" label="Cliente" />
<mad-col field="estado_id" label="Estado" width="130"
badge="1:info:Novo|2:warning:Em separação|3:primary:Enviado|4:success:Entregue|5:danger:Cancelado" />
<mad-col field="valor_total" label="Valor" width="130" right money="R$" />
</mad-columns>
<mad-actions>
<mad-act method="onAprovar" icon="check" label="Aprovar" primary
when-field="estado_id" when-in="1,2" />
<mad-act method="onEntregar" icon="truck" label="Entregar" primary
when-field="estado_id" when-value="3" />
<mad-action-group icon="more-horizontal" label="Mais">
<mad-act method="onCancelar" icon="ban" label="Cancelar" danger
confirm="Cancelar este pedido?"
when-field="estado_id" when-nin="4,5" />
{{-- mad-action é alias de mad-act — mesmo compilador, mesmos atributos. --}}
<mad-action method="onReabrir" icon="rotate-ccw" label="Reabrir"
display-condition="TutorGridsAcoes::podeReabrir" />
</mad-action-group>
<mad-del confirm="Excluir este pedido (demonstração)?" />
</mad-actions>
</mad-grid>
app/control/Tutor/TutorGridsAcoes.php
/** Novo(1)/Em separação(2) -> Enviado(3). */
public function onAprovar(int $id): MadResponse
{
$pedido = TutorDemoPedido::findOrFail($id);
$pedido->estado_id = 3;
$pedido->save();
return (new MadResponse())
->toast("Pedido #{$id} aprovado — agora está Enviado.", 'success')
->manageRow($id, static::class);
}
Buscar pedido (mad-seek)
Campo de busca modal com múltiplas colunas — seleciona o registro e dispara uma ação.
resources/views/tutor/examples/grids-acoes/buscar.blade.php
<mad-form submit="onBuscarPedido">
<mad-seek name="pedidoBuscaId" model="TutorDemoPedido" display="descricao"
label="Pedido" placeholder="Buscar por descrição..." modal-title="Selecionar pedido"
per-page="8">
<mad-column field="id" label="Cod." width="70" sort />
<mad-column field="descricao" label="Descrição" sort filter />
<mad-column field="valor_total" label="Valor" width="120" right money="R$" />
</mad-seek>
<mad-btn type="submit" variant="primary" icon="search">Buscar</mad-btn>
</mad-form>
app/control/Tutor/TutorGridsAcoes.php
public function onBuscarPedido(): MadResponse
{
if ($this->pedidoBuscaId === '') {
return (new MadResponse())->toast('Selecione um pedido na busca.', 'warning');
}
$pedido = TutorDemoPedido::with(['cliente', 'estado'])->find($this->pedidoBuscaId);
if (!$pedido) {
return (new MadResponse())->toast('Pedido não encontrado.', 'danger');
}
$cliente = $pedido->cliente->nome ?? '—';
$estado = $pedido->estado->nome ?? '—';
return (new MadResponse())->toast(
"Pedido #{$pedido->id} — {$pedido->descricao} — cliente {$cliente} — estado {$estado}.",
'success'
);
}
Código-fonte completo da página
app/control/Tutor/TutorGridsAcoes.php
<?php
namespace App\Control\Tutor;
use App\Models\TutorDemo\TutorDemoPedido;
use App\Support\Tutor\TutorDemoSeed;
use Mad\Grid\MadDataGrid;
use Mad\Http\MadResponse;
/**
* TutorGridsAcoes — ações de linha: mad-act, mad-action (alias), mad-nav,
* mad-del, mad-action-group, mad-seek.
*
* NÃO estende TutorPage: <mad-grid self> exige que o HOST seja literalmente
* uma subclasse de MadDataGrid (colunas/ações leem $model/$with/métodos
* DESTA classe) — TutorPage estende MadComponent puro, sem esse contrato.
* view() abaixo aponta pro MESMO caminho que o TutorCatalog usaria
* (tutor.grids.acoes) — TutorCatalog/TutorPage.php não são tocados.
*/
class TutorGridsAcoes extends MadDataGrid
{
protected static string $wrapper = self::INTERNAL;
protected string $model = TutorDemoPedido::class;
protected array $with = ['cliente', 'estado'];
protected string $defaultSort = 'id DESC';
protected string $actionSide = 'left';
/** Campo do <mad-seek> do exemplo "Buscar pedido". */
public string $pedidoBuscaId = '';
public function mount(array $params = []): void
{
TutorDemoSeed::ensure();
parent::mount($params);
}
// ── Ações de linha ──────────────────────────────────────────────────
/** Novo(1)/Em separação(2) -> Enviado(3). */
public function onAprovar(int $id): MadResponse
{
$pedido = TutorDemoPedido::findOrFail($id);
$pedido->estado_id = 3;
$pedido->save();
return (new MadResponse())
->toast("Pedido #{$id} aprovado — agora está Enviado.", 'success')
->manageRow($id, static::class);
}
/** Enviado(3) -> Entregue(4). */
public function onEntregar(int $id): MadResponse
{
$pedido = TutorDemoPedido::findOrFail($id);
$pedido->estado_id = 4;
$pedido->save();
return (new MadResponse())
->toast("Pedido #{$id} marcado como Entregue.", 'success')
->manageRow($id, static::class);
}
/** Qualquer estado exceto Entregue(4)/Cancelado(5) -> Cancelado(5). */
public function onCancelar(int $id): MadResponse
{
$pedido = TutorDemoPedido::findOrFail($id);
$pedido->estado_id = 5;
$pedido->save();
return (new MadResponse())
->toast("Pedido #{$id} cancelado.", 'warning')
->manageRow($id, static::class);
}
/** Cancelado(5) -> Novo(1) — reabre o pedido (via a tag <mad-action>, alias de mad-act). */
public function onReabrir(int $id): MadResponse
{
$pedido = TutorDemoPedido::findOrFail($id);
$pedido->estado_id = 1;
$pedido->save();
return (new MadResponse())
->toast("Pedido #{$id} reaberto — voltou para Novo.", 'info')
->manageRow($id, static::class);
}
/**
* <mad-del> exige onMadGridDelete(int $id) na subclasse (o built-in só
* existe na MadGrid zero-PHP). Aqui a exclusão é SIMULADA de propósito:
* os 150 pedidos da fixture são compartilhados por TODOS os visitantes
* do Tutor (TutorDemoSeed::ensure() só re-semeia quando a tabela fica
* vazia) — apagar de verdade a cada clique de demonstração esgotaria o
* dataset com o tempo. removeRow() tira a linha da TELA sem tocar o
* banco; um novo carregamento da página mostra o pedido de novo.
*/
public function onMadGridDelete(int $id): MadResponse
{
return (new MadResponse())
->toast("Exclusão simulada — o pedido #{$id} não foi removido do banco (dado de demonstração compartilhado).", 'info')
->removeRow($id, static::class);
}
/** Display-condition de AÇÃO: recebe array (não stdClass — isso é regra de coluna). */
public static function podeReabrir(array $row): bool
{
return (int) ($row['estado_id'] ?? 0) === 5;
}
// ── mad-seek: localizar um pedido pela descrição ─────────────────────
public function onBuscarPedido(): MadResponse
{
if ($this->pedidoBuscaId === '') {
return (new MadResponse())->toast('Selecione um pedido na busca.', 'warning');
}
$pedido = TutorDemoPedido::with(['cliente', 'estado'])->find($this->pedidoBuscaId);
if (!$pedido) {
return (new MadResponse())->toast('Pedido não encontrado.', 'danger');
}
$cliente = $pedido->cliente->nome ?? '—';
$estado = $pedido->estado->nome ?? '—';
return (new MadResponse())->toast(
"Pedido #{$pedido->id} — {$pedido->descricao} — cliente {$cliente} — estado {$estado}.",
'success'
);
}
protected function view(): string|array
{
return 'tutor.grids.acoes';
}
}
resources/views/tutor/grids/acoes.blade.php
<x-tutor-page page="grids_acoes">
<mad-callout type="info" title="Navegação de exemplo" icon="info">
O <code><mad-nav></code> abaixo aponta para a página <strong>Texto</strong>
(Formulários) só pra ilustrar a navegação — o Tutor não tem uma tela de
"detalhe do pedido" dedicada. Numa tela real o target seria o
form/detalhe do próprio registro (ex.: <code>PedidoForm::onEdit({id})</code>).
</mad-callout>
<x-tutor-demo demo="tutor.examples.grids-acoes.navegar"
title="Navegar (mad-nav)" desc="mad-nav abre outra tela — nunca mad-act pra isso." />
<x-tutor-demo demo="tutor.examples.grids-acoes.completas"
title="Ações completas" desc="mad-act, mad-action (alias), mad-action-group, mad-del, when-field e display-condition no mesmo grid."
php="TutorGridsAcoes::onAprovar" />
<x-tutor-demo demo="tutor.examples.grids-acoes.buscar"
title="Buscar pedido (mad-seek)" desc="Campo de busca modal com múltiplas colunas — seleciona o registro e dispara uma ação."
php="TutorGridsAcoes::onBuscarPedido" />
</x-tutor-page>