Campos ligados a banco
mad-dbcombo-field lendo a fixture TutorDemoCliente (conexão business, ~40 registros, TomSelect client-side).
Options carregadas da fixture TutorDemoCliente (business.tutor_clientes, ~40 registros) — busca client-side no dropdown.
<mad-dbcombo-field name="cliente_basico_id" label="Cliente"
model="TutorDemoCliente" database="business"
display="{nome}" order-by="nome"
placeholder="Selecione um cliente..."
hint="Options carregadas da fixture TutorDemoCliente (business.tutor_clientes, ~40 registros) — busca client-side no dropdown." />
display="{descricao} - R$ {valor_total}" combinado com :filters (WHERE valor_total > 100) sobre TutorDemoPedido.
display composto ({descricao} - R$ {valor_total}) + :filters aplicando WHERE valor_total > 100.
<mad-dbcombo-field name="pedido_alto_valor_id" label="Pedido (valor acima de R$ 100)"
model="TutorDemoPedido" database="business"
display="{descricao} - R$ {valor_total}" order-by="valor_total"
:filters="[['valor_total', '>', 100]]"
placeholder="Selecione um pedido de alto valor..."
hint="display composto ({descricao} - R$ {valor_total}) + :filters aplicando WHERE valor_total > 100." />
Escolher a categoria filtra o segundo combo pelos pedidos daquela categoria (depends-on + depends-column="categoria_id").
depends-on/depends-column recarrega os pedidos filtrando por categoria_id — sem mad:change manual.
<mad-form-grid :cols="2">
<mad-dbcombo-field name="categoria_cascata_id" label="Categoria"
model="TutorDemoCategoria" database="business"
display="{nome}" order-by="nome"
placeholder="Selecione uma categoria..." />
<mad-dbcombo-field name="pedido_cascata_id" label="Pedido"
model="TutorDemoPedido" database="business"
display="{descricao}" order-by="descricao"
depends-on="categoria_cascata_id" depends-column="categoria_id"
placeholder="Selecione a categoria primeiro..."
hint="depends-on/depends-column recarrega os pedidos filtrando por categoria_id — sem mad:change manual." />
</mad-form-grid>
mad:change dispara TutorDbComboSelect::onClienteSelecionado mesmo sem envolver o campo num mad-form.
<mad-dbcombo-field name="cliente_wire_id" label="Cliente (dispara ação ao selecionar)"
model="TutorDemoCliente" database="business"
display="{nome}" order-by="nome"
placeholder="Selecione para ver o resumo..."
mad:change="onClienteSelecionado" />
/**
* mad:change do exemplo "Ação ao selecionar" — prova que um db-field
* dispara wire normalmente, mesmo fora de um <mad-form>.
*/
public function onClienteSelecionado(string $value): MadResponse
{
$id = (int) $value;
if ($id <= 0) {
return (new MadResponse())->toast('Nenhum cliente selecionado.', 'warning');
}
$cliente = TutorDemoCliente::query()->find($id);
if ($cliente === null) {
return (new MadResponse())->toast('Cliente não encontrado.', 'danger');
}
$pedidos = $cliente->pedidos()->count();
return (new MadResponse())->toast(
"{$cliente->nome} · {$cliente->cidade}/{$cliente->uf} · {$pedidos} pedido(s)",
'success',
'onClienteSelecionado'
);
}
mad-dbselect-field para listas pequenas (os 5 estados de pedido) — sem TomSelect, sem busca.
mad-dbselect-field é alias de compatibilidade de mad-dbcombo-field (mesmo componente, mesmo HTML) — em código novo prefira mad-dbcombo-field diretamente.
<mad-dbselect-field name="estado_select_id" label="Estado do pedido"
model="TutorDemoEstadoPedido" database="business"
display="{nome}" order-by="ordem"
placeholder="Selecione um estado..."
hint="mad-dbselect-field é alias de compatibilidade de mad-dbcombo-field (mesmo componente, mesmo HTML) — em código novo prefira mad-dbcombo-field diretamente." />
mad-dbentry-field autocompleta a partir da coluna tutor_clientes.cidade (runtime-only, sem preview no editor visual).
<mad-dbentry-field name="cidade_entry" label="Cidade"
model="TutorDemoCliente" database="business" column="cidade"
min-length="1" placeholder="Digite uma cidade..." />
Tags filhas <fill> preenchem outros campos a partir do registro escolhido no combo — resolução 100% server-side, sem expor o registro no cliente.
<mad-dbcombo-field name="fill_cliente_id" label="Cliente (dispara auto-fill)"
model="TutorDemoCliente" database="business"
display="{nome}" order-by="nome"
placeholder="Selecione um cliente...">
<fill field="fill_email" from="email" />
<fill field="fill_cidade" from="cidade" />
<fill field="fill_uf" from="uf" transform="upper" />
</mad-dbcombo-field>
<mad-form-grid :cols="3">
<mad-input-field name="fill_email" label="E-mail (preenchido)" readonly />
<mad-input-field name="fill_cidade" label="Cidade (preenchida)" readonly />
<mad-input-field name="fill_uf" label="UF (preenchida, upper)" readonly />
</mad-form-grid>
mad-fill, mas o framework tem dois
mecanismos de auto-preenchimento com nomes parecidos: a tag sem prefixo
<fill field="..." from="..." /> — filha de mad-dbcombo-field,
mad-dbselect-field e mad-dbunique-search-field (doc
dbcombo-field.md, seção "Auto-fill do registro selecionado") — e o componente
<mad-fill target="..." source="..." />, que só existe como filho de
<mad-seek> (fora do catálogo desta página; ver mad_cheat f-select).
Como esta página cobre exatamente os combos/selects ligados a banco, o exemplo acima usa o
<fill> sem prefixo — a variante que de fato combina com
mad-dbcombo-field/mad-dbselect-field. Nenhuma rota ou controller
extra foi necessária.Código-fonte completo da página
<?php
namespace App\Control\Tutor;
use App\Models\TutorDemo\TutorDemoCliente;
use App\Support\Tutor\TutorPage;
use Mad\Http\MadResponse;
/**
* TutorDbComboSelect — combos/selects ligados a banco (mad-dbcombo-field,
* mad-dbselect-field, mad-dbentry-field) + auto-preenchimento via <fill>.
*/
class TutorDbComboSelect extends TutorPage
{
protected string $catalogKey = 'db_combo_select';
/**
* mad:change do exemplo "Ação ao selecionar" — prova que um db-field
* dispara wire normalmente, mesmo fora de um <mad-form>.
*/
public function onClienteSelecionado(string $value): MadResponse
{
$id = (int) $value;
if ($id <= 0) {
return (new MadResponse())->toast('Nenhum cliente selecionado.', 'warning');
}
$cliente = TutorDemoCliente::query()->find($id);
if ($cliente === null) {
return (new MadResponse())->toast('Cliente não encontrado.', 'danger');
}
$pedidos = $cliente->pedidos()->count();
return (new MadResponse())->toast(
"{$cliente->nome} · {$cliente->cidade}/{$cliente->uf} · {$pedidos} pedido(s)",
'success',
'onClienteSelecionado'
);
}
}
<x-tutor-page page="db_combo_select">
<x-tutor-demo demo="tutor.examples.db-combo-select.basico"
title="Combo básico" desc="mad-dbcombo-field lendo a fixture TutorDemoCliente (conexão business, ~40 registros, TomSelect client-side)." />
<x-tutor-demo demo="tutor.examples.db-combo-select.composto-filtro"
title="Display composto + filtro" desc="display="{descricao} - R$ {valor_total}" combinado com :filters (WHERE valor_total > 100) sobre TutorDemoPedido." />
<x-tutor-demo demo="tutor.examples.db-combo-select.cascata"
title="Cascata (depends-on)" desc="Escolher a categoria filtra o segundo combo pelos pedidos daquela categoria (depends-on + depends-column="categoria_id")." />
<x-tutor-demo demo="tutor.examples.db-combo-select.wire-change"
title="Ação ao selecionar (mad:change)" desc="mad:change dispara TutorDbComboSelect::onClienteSelecionado mesmo sem envolver o campo num mad-form."
php="TutorDbComboSelect::onClienteSelecionado" />
<x-tutor-demo demo="tutor.examples.db-combo-select.dbselect"
title="Select nativo (DB)" desc="mad-dbselect-field para listas pequenas (os 5 estados de pedido) — sem TomSelect, sem busca." />
<x-tutor-demo demo="tutor.examples.db-combo-select.dbentry"
title="Texto com sugestão do banco" desc="mad-dbentry-field autocompleta a partir da coluna tutor_clientes.cidade (runtime-only, sem preview no editor visual)." />
<x-tutor-demo demo="tutor.examples.db-combo-select.fill"
title="Auto-preenchimento (<fill>)" desc="Tags filhas <fill> preenchem outros campos a partir do registro escolhido no combo — resolução 100% server-side, sem expor o registro no cliente." />
<mad-callout type="info" title="mad-fill × <fill>" icon="info">
O catálogo lista a tag como <code>mad-fill</code>, mas o framework tem <strong>dois</strong>
mecanismos de auto-preenchimento com nomes parecidos: a tag <strong>sem prefixo</strong>
<code><fill field="..." from="..." /></code> — filha de <code>mad-dbcombo-field</code>,
<code>mad-dbselect-field</code> e <code>mad-dbunique-search-field</code> (doc
<code>dbcombo-field.md</code>, seção "Auto-fill do registro selecionado") — e o componente
<code><mad-fill target="..." source="..." /></code>, que só existe como filho de
<code><mad-seek></code> (fora do catálogo desta página; ver <code>mad_cheat f-select</code>).
Como esta página cobre exatamente os combos/selects ligados a banco, o exemplo acima usa o
<code><fill></code> sem prefixo — a variante que de fato combina com
<code>mad-dbcombo-field</code>/<code>mad-dbselect-field</code>. Nenhuma rota ou controller
extra foi necessária.
</mad-callout>
</x-tutor-page>