MAD Lab
/
Tutor > Campos ligados a banco > Combos e selects (DB)

Combos e selects (DB)

Campos ligados a banco

mad-dbcombo-field mad-dbselect-field mad-dbentry-field mad-fill
Combo básico

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.

resources/views/tutor/examples/db-combo-select/basico.blade.php
<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 composto + filtro

display=&quot;{descricao} - R$ {valor_total}&quot; combinado com :filters (WHERE valor_total > 100) sobre TutorDemoPedido.

display composto ({descricao} - R$ {valor_total}) + :filters aplicando WHERE valor_total > 100.

resources/views/tutor/examples/db-combo-select/composto-filtro.blade.php
<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." />
Cascata (depends-on)

Escolher a categoria filtra o segundo combo pelos pedidos daquela categoria (depends-on + depends-column=&quot;categoria_id&quot;).

depends-on/depends-column recarrega os pedidos filtrando por categoria_id — sem mad:change manual.

resources/views/tutor/examples/db-combo-select/cascata.blade.php
<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>
Ação ao selecionar (mad:change)

mad:change dispara TutorDbComboSelect::onClienteSelecionado mesmo sem envolver o campo num mad-form.

resources/views/tutor/examples/db-combo-select/wire-change.blade.php
<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" />
app/control/Tutor/TutorDbComboSelect.php
/**
 * 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'
    );
}
Select nativo (DB)

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.

resources/views/tutor/examples/db-combo-select/dbselect.blade.php
<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." />
Texto com sugestão do banco

mad-dbentry-field autocompleta a partir da coluna tutor_clientes.cidade (runtime-only, sem preview no editor visual).

resources/views/tutor/examples/db-combo-select/dbentry.blade.php
<mad-dbentry-field name="cidade_entry" label="Cidade"
    model="TutorDemoCliente" database="business" column="cidade"
    min-length="1" placeholder="Digite uma cidade..." />
Auto-preenchimento (&lt;fill&gt;)

Tags filhas &lt;fill&gt; preenchem outros campos a partir do registro escolhido no combo — resolução 100% server-side, sem expor o registro no cliente.

resources/views/tutor/examples/db-combo-select/fill.blade.php
<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 × <fill>
O catálogo lista a tag como 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
app/control/Tutor/TutorDbComboSelect.php
<?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'
        );
    }
}
resources/views/tutor/db/combo-select.blade.php
<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=&quot;{descricao} - R$ {valor_total}&quot; 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=&quot;categoria_id&quot;)." />

    <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 (&lt;fill&gt;)" desc="Tags filhas &lt;fill&gt; 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>&lt;fill field="..." from="..." /&gt;</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>&lt;mad-fill target="..." source="..." /&gt;</code>, que só existe como filho de
        <code>&lt;mad-seek&gt;</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>&lt;fill&gt;</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>