Docs›Services›MadResponse
Services

MadResponse

Response builder fluente com 30+ ops parciais.

Mad\Http\MadResponse é o builder fluente de respostas parciais do MadWire — toda action de MadComponent que precisa atualizar a UI sem um full re-render retorna (ou envia) uma instância dele. Cada método adiciona uma op (uma instrução serializável) à lista interna $ops, que o JavaScript do client aplica em sequência via Mad.applyOps().

Catálogo completo de ops

Esta página cobre construção, encadeamento e o ciclo de vida da classe. Para a lista exaustiva de métodos (manipulação de DOM, toasts, navegação, kanban, gantt, tree-view, detail-form, recarregar combos/checklists...), ver MadResponse — todas as ops.

Construção e encadeamento

Toda op retorna $this (tipo static) — encadeável livremente:

use Mad\Http\MadResponse;

return new MadResponse(); // sem ops — dispara re-render total do componente

return (new MadResponse())
    ->toast('Salvo!', 'success')
    ->closeDrawer();
public function onAprovar(int $id): MadResponse
{
    Pedido::find($id)->update(['status' => 'aprovado']);

    return (new MadResponse())
        ->toast('Aprovado!', 'success')
        ->html('#status-badge', '<span class="mad-badge mad-badge-success">Aprovado</span>')
        ->closeDrawer()
        ->manageRow($id, PedidoListagem::class);
}

void vs MadResponse

Quando uma action só muda state (props públicas, $form->set()), retorne void — o framework calcula o diff e gera as ops (val, bind, reload_*) automaticamente. Reserve MadResponse explícito para UX que o diff de state não cobre: toast, fechar modal/drawer, navegar, manipular DOM fora do form.

// void — só muda state. O handler faz o diff e gera val/bind/reload_* sozinho.
public function onTipoChange(string $tipo): void
{
    $this->form->set('descricao', TipoProduto::find($tipo)->descricao);
}

// MadResponse — quando você precisa de UX explícito (toast, fechar, navegar)
public function onSave(): MadResponse
{
    $produto = Produto::findOrNew($this->registroId);
    $this->form->save($produto);

    return (new MadResponse())
        ->toast('Salvo!', 'success')
        ->closeDrawer();
}

Ver Auto-bind para como o diff funciona por dentro.

Ops parciais vs full re-render

Sem nenhuma op (new MadResponse() "vazio"), o componente sofre re-render total: o state é serializado, view() é chamado de novo, e o DOM inteiro do wrapper é substituído. Cada op específica (html, val, manageRow...) é parcial — atualiza só o alvo necessário.

Em listagens grandes, evite re-render total

Prefira manageRow()/manageCard() para atualizar/inserir uma linha específica, ou html('#regiao', ...) para uma área isolada — ver Render parcial.

Atalhos estáticos

use Mad\Http\MadResponse;

// Atalhos estáticos — criam, preenchem e ENVIAM (encerram a execução)
MadResponse::ok('Operação realizada com sucesso!'); // toast success + send()
MadResponse::err('Falha ao processar.');             // toast danger  + send()

// Abre um MadComponent detectando o wrapper sozinho (igual MadAction::auto())
return MadResponse::open('DocProdutoForm', ['id' => $id]);
return MadResponse::open('DocProdutoForm', ['id' => $id], 'onEdit'); // método custom
Método estáticoComportamento
ok($message = '...')Cria, adiciona toast success e já chama send() — não retorna.
err($message)Mesma ideia, toast danger.
open($class, $params = [], $method = 'show')Abre um MadComponent com auto-detect de wrapper (delega para MadAction).

send() vs getOps() vs merge()

A maioria das actions de MadComponent apenas return o MadResponse — o MadComponentHandler chama getOps() internamente e serializa a resposta. send() é para o caso explícito de métodos estáticos chamados direto pelo client (lookups, field actions via fetch) — nesse contexto não há um retorno tipado pro handler interceptar, então o método precisa imprimir o JSON e encerrar a execução sozinho:

// Métodos estáticos chamados pelo client (field actions, lookups via fetch) —
// não retornam: encerram a request com send().
public static function onExitCep(): void
{
    $cep  = preg_replace('/\D/', '', $_POST['cep'] ?? '');
    $data = json_decode(file_get_contents("https://viacep.com.br/ws/{$cep}/json/"), true);

    (new MadResponse)
        ->val('#logradouro', $data['logradouro'])
        ->val('#bairro',     $data['bairro'])
        ->val('#cidade',     $data['localidade'])
        ->val('#uf',         $data['uf'])
        ->toast('CEP preenchido!', 'success')
        ->send();
}
MétodoRetornoUso
getOps()arrayArray de ops, sem enviar nem encerrar — usado internamente pelo MadComponentHandler.
merge(MadResponse $other)staticConcatena as ops de outro MadResponse neste (útil ao compor respostas de helpers como MadToast/MadValidationException).
send()neverManda Content-Type: application/json, echo do JSON + exit — só em métodos estáticos chamados direto via AJAX.
emit()voidecho de um <script> inline que chama Mad.applyOps(...) — só para dispatch clássico (página/janela cujo retorno NÃO é serializado pelo wire), ex.: redirect('LoginForm')->emit() pós-logout.
Em endpoint AJAX, nunca emit()

emit() devolve HTML (<script>), não JSON — quem consome a resposta com Mad.applyOps(await res.json()) quebra. Um método public static chamado por fetch/Mad.exec deve terminar em send(), ou fazer o echo json_encode($resp->getOps()) explicitamente. emit() serve apenas quando o navegador está carregando a saída como documento.

getOps() e send() ainda anexam os dumps pendentes de mad_dump_modal()/mdm() via MadDumpModal::inject(). Se houver payload de debug ativo (MadLogService), send() troca o corpo de array-de-ops puro para { "ops": [...], "_debug": {...} }.

Próximos passos