MAD Lab
/
Tutor > Estrutura de formulário > Layouts de formulário

Layouts de formulário

Estrutura de formulário

mad-form-stack mad-quick-form mad-form-token
Stack isolado

mad-form-stack empilha campos de larguras diferentes sem forçar um grid.

resources/views/tutor/examples/estrutura-layouts/stack-basico.blade.php
<mad-form-stack>
    <mad-input-field name="titulo_layout" label="Título do anúncio" placeholder="Ex: Bicicleta usada, poucos km" />
    <mad-textarea-field name="descricao_layout" label="Descrição" :rows="3" placeholder="Detalhe o item..." />
    <mad-input-field name="local_layout" label="Local de retirada" placeholder="Bairro, cidade" />
</mad-form-stack>
Grid + stack na mesma seção

Padrão comum: grid para campos curtos lado a lado, stack para o campo longo logo abaixo.

resources/views/tutor/examples/estrutura-layouts/grid-mais-stack.blade.php
<mad-form-section title="Cadastro de vendedor" icon="store">
    <mad-form-grid :cols="2">
        <mad-input-field name="nome_vendedor" label="Nome" placeholder="Nome completo" />
        <mad-input-field name="email_vendedor" label="E-mail" type="email" />
    </mad-form-grid>

    <mad-form-stack>
        <mad-textarea-field name="bio_vendedor" label="Sobre o vendedor" :rows="3"
            placeholder="Um texto curto sobre a loja/vendedor..." />
    </mad-form-stack>
</mad-form-section>
Busca com cadastro rápido (multi-campo)

mad-quick-form dentro de mad-dbunique-search-field: cadastra um cliente inline, sem sair da tela.

resources/views/tutor/examples/estrutura-layouts/quick-form-busca.blade.php
<mad-dbunique-search-field name="cliente_quickform" label="Cliente"
    database="business" model="TutorDemoCliente" key="id" display="{nome}" order-by="nome"
    placeholder="Digite para buscar um cliente..."
    no-results-message="Não achou? Cadastre rapidinho:">
    <mad-quick-form action="TutorEstruturaLayouts::onQuickAddCliente" label="Cadastrar" icon="check"
        message="Novo cliente">
        <mad-input-field name="nome" label="Nome" required />
        <mad-input-field name="cidade" label="Cidade" />
        <mad-input-field name="uf" label="UF" />
    </mad-quick-form>
</mad-dbunique-search-field>
app/control/Tutor/TutorEstruturaLayouts.php
/**
 * Quick register multi-campo do exemplo "Busca com cadastro rápido" —
 * chamado por MadQuickRegisterService::onRun (contrato: recebe
 * ['term','fields','field_name','model','database','key','display'] e
 * devolve ['value','label','toast'?]).
 */
public static function onQuickAddCliente(array $params): array
{
    $fields = $params['fields'] ?? [];
    $nome   = trim((string) ($fields['nome'] ?? $params['term'] ?? ''));

    if ($nome === '') {
        throw new \Exception('Informe o nome do cliente.');
    }

    $cliente = TutorDemoCliente::query()->create([
        'nome'   => $nome,
        'email'  => Str::slug($nome, '.') . '@quickform.tutor',
        'cidade' => trim((string) ($fields['cidade'] ?? '')) ?: 'Não informado',
        'uf'     => strtoupper(trim((string) ($fields['uf'] ?? ''))) ?: '--',
    ]);

    return [
        'value' => $cliente->id,
        'label' => $cliente->nome,
        'toast' => "Cliente \"{$cliente->nome}\" cadastrado via quick-form!",
    ];
}
Combo com cadastro rápido (campo único)

mad-quick-form também funciona em mad-dbcombo-field — aqui com um único campo (nome).

resources/views/tutor/examples/estrutura-layouts/quick-form-combo.blade.php
<mad-dbcombo-field name="categoria_quickform" label="Categoria"
    model="TutorDemoCategoria" database="business" display="{nome}" order-by="nome"
    no-results-message="Categoria nova? Cadastre:">
    <mad-quick-form action="TutorEstruturaLayouts::onQuickAddCategoria" label="Adicionar" icon="plus"
        message="Nova categoria">
        <mad-input-field name="nome" label="Nome da categoria" required />
    </mad-quick-form>
</mad-dbcombo-field>
app/control/Tutor/TutorEstruturaLayouts.php
/**
 * Quick register de campo único do exemplo "Combo com cadastro rápido" —
 * só usa o texto digitado (term), sem mini-form de campos extras.
 */
public static function onQuickAddCategoria(array $params): array
{
    $nome = trim((string) ($params['term'] ?? ''));

    if ($nome === '') {
        throw new \Exception('Informe o nome da categoria.');
    }

    $categoria = TutorDemoCategoria::query()->create(['nome' => $nome]);

    return [
        'value' => $categoria->id,
        'label' => $categoria->nome,
        'toast' => "Categoria \"{$categoria->nome}\" cadastrada via quick-form!",
    ];
}
mad-form-token não tem demo aqui
O catálogo lista mad-form-token para esta página, mas o MCP do framework (mad_find/mad_props) não reconhece esse componente como tag documentada — e o código-fonte confirma o motivo: <mad-form> já chama Mad\Form\MadFormRegistry::token() internamente ao final do próprio render (packages/mad-framework/src/mad/views/components/form.blade.php) e injeta sozinho o hidden __mad_form. O arquivo packages/mad-framework/src/mad/views/components/form-token.blade.php existe mas é redundante — usá-lo à parte duplicaria o input. Ver relatório desta tarefa para o detalhamento.
Código-fonte completo da página
app/control/Tutor/TutorEstruturaLayouts.php
<?php

namespace App\Control\Tutor;

use App\Models\TutorDemo\TutorDemoCategoria;
use App\Models\TutorDemo\TutorDemoCliente;
use App\Support\Tutor\TutorPage;
use Illuminate\Support\Str;

/**
 * TutorEstruturaLayouts — página "Layouts de formulário" do MAD Lab.
 *
 * Cobre mad-form-stack (revisitado em combinação com mad-form-grid, padrão de
 * "layout misto" dentro da mesma seção) e mad-quick-form (cadastro rápido
 * inline no dropdown de um campo de busca/combo ligado a banco).
 *
 * mad-form-token — terceira tag do catálogo — NÃO tem demo aqui: é um
 * componente legado (packages/mad-framework/src/mad/views/components/form-token.blade.php)
 * que mad_find/mad_props do MCP não reconhecem como componente documentado, e
 * o próprio <mad-form> já chama Mad\Form\MadFormRegistry::token() internamente
 * ao fim do render (ver form.blade.php) — usá-lo à parte duplicaria o hidden
 * input __mad_form. Ver mad-callout no fim da página e o relatório desta
 * tarefa para o detalhamento.
 */
class TutorEstruturaLayouts extends TutorPage
{
    protected string $catalogKey = 'estrutura_layouts';

    /**
     * Quick register multi-campo do exemplo "Busca com cadastro rápido" —
     * chamado por MadQuickRegisterService::onRun (contrato: recebe
     * ['term','fields','field_name','model','database','key','display'] e
     * devolve ['value','label','toast'?]).
     */
    public static function onQuickAddCliente(array $params): array
    {
        $fields = $params['fields'] ?? [];
        $nome   = trim((string) ($fields['nome'] ?? $params['term'] ?? ''));

        if ($nome === '') {
            throw new \Exception('Informe o nome do cliente.');
        }

        $cliente = TutorDemoCliente::query()->create([
            'nome'   => $nome,
            'email'  => Str::slug($nome, '.') . '@quickform.tutor',
            'cidade' => trim((string) ($fields['cidade'] ?? '')) ?: 'Não informado',
            'uf'     => strtoupper(trim((string) ($fields['uf'] ?? ''))) ?: '--',
        ]);

        return [
            'value' => $cliente->id,
            'label' => $cliente->nome,
            'toast' => "Cliente \"{$cliente->nome}\" cadastrado via quick-form!",
        ];
    }

    /**
     * Quick register de campo único do exemplo "Combo com cadastro rápido" —
     * só usa o texto digitado (term), sem mini-form de campos extras.
     */
    public static function onQuickAddCategoria(array $params): array
    {
        $nome = trim((string) ($params['term'] ?? ''));

        if ($nome === '') {
            throw new \Exception('Informe o nome da categoria.');
        }

        $categoria = TutorDemoCategoria::query()->create(['nome' => $nome]);

        return [
            'value' => $categoria->id,
            'label' => $categoria->nome,
            'toast' => "Categoria \"{$categoria->nome}\" cadastrada via quick-form!",
        ];
    }
}
resources/views/tutor/estrutura/layouts.blade.php
<x-tutor-page page="estrutura_layouts">
    <x-tutor-demo demo="tutor.examples.estrutura-layouts.stack-basico"
        title="Stack isolado" desc="mad-form-stack empilha campos de larguras diferentes sem forçar um grid." />

    <x-tutor-demo demo="tutor.examples.estrutura-layouts.grid-mais-stack"
        title="Grid + stack na mesma seção" desc="Padrão comum: grid para campos curtos lado a lado, stack para o campo longo logo abaixo." />

    <x-tutor-demo demo="tutor.examples.estrutura-layouts.quick-form-busca"
        title="Busca com cadastro rápido (multi-campo)" desc="mad-quick-form dentro de mad-dbunique-search-field: cadastra um cliente inline, sem sair da tela."
        php="TutorEstruturaLayouts::onQuickAddCliente" />

    <x-tutor-demo demo="tutor.examples.estrutura-layouts.quick-form-combo"
        title="Combo com cadastro rápido (campo único)" desc="mad-quick-form também funciona em mad-dbcombo-field — aqui com um único campo (nome)."
        php="TutorEstruturaLayouts::onQuickAddCategoria" />

    <mad-callout type="warning" title="mad-form-token não tem demo aqui" icon="alert-triangle">
        O catálogo lista <code>mad-form-token</code> para esta página, mas o MCP do framework
        (<code>mad_find</code>/<code>mad_props</code>) não reconhece esse componente como tag documentada —
        e o código-fonte confirma o motivo: <code>&lt;mad-form&gt;</code> já chama
        <code>Mad\Form\MadFormRegistry::token()</code> internamente ao final do próprio render
        (packages/mad-framework/src/mad/views/components/form.blade.php) e injeta sozinho o
        hidden <code>__mad_form</code>. O arquivo
        <code>packages/mad-framework/src/mad/views/components/form-token.blade.php</code> existe mas é
        redundante — usá-lo à parte duplicaria o input. Ver relatório desta tarefa para o detalhamento.
    </mad-callout>
</x-tutor-page>