Docs›Componentes (Admin)›Row-attach (mad-nav row)
Componentes (Admin)

Row-attach (mad-nav row)

Form aberto anexado à linha da grid (quick edit) em vez da cortina, via atributo booleano row do mad-nav.

Variante de abertura de formulario a partir de uma listagem (MadDataGrid): em vez de abrir o form na cortina lateral (drawer), o form abre anexado a linha clicada — uma <tr> extra logo abaixo da linha, com o form dentro em colspan total, no estilo "quick edit" do GitHub/Linear. O usuario edita sem perder o contexto visual da listagem.

O mesmo form control serve os dois contextos. Nenhuma mudanca e necessaria na classe do form — nem no onSave. Quem decide a apresentacao e o chamador (a action da grid), nao o componente.

Tag

row e atributo booleano do <mad-nav> (docblock canonico: MadGridCompiler, secao <mad-nav>):

<mad-grid model="User" per-page="20">
    <mad-actions>
        <mad-nav icon="pencil" :label="__('mad.edit')"
                 target="UserForm::onEdit({id})" row />
    </mad-actions>
</mad-grid>

Funciona tambem dentro de <mad-action-group> e convive com :params, navigate=, display-condition — so troca o modo de abertura.

Props

Prop Tipo Default Descricao
row bool false Abre o alvo anexado a linha da grid em vez de drawer/modal

Precedencia de apresentacao (em GridAction::getNavAttr()): row > drawer > auto-detect pelo $wrapper do componente alvo.

Camada Quem declara Papel
$wrapper no form (INTERNAL/MODAL/DRAWER) o componente apresentacao padrao standalone
row / drawer na action o chamador (<mad-nav>) override por invocacao
$that->isRowAttach() na view a view do form adaptacao opcional ao contexto

Builder fluente

// GridBuilder
$grid->nav('pencil', 'Editar', UserForm::class, 'onEdit', row: true);

// GridActBuilder (acucar)
$grid->act('edit', 'pencil', 'Editar')->attachRow(UserForm::class, 'onEdit');

// GridAction direto
GridAction::make('edit')->nav(UserForm::class, 'onEdit')->row();

View adaptativa

MadComponent::isRowAttach(): bool vale no GET inicial e em todos os re-renders do MadWire (o flag e persistido no mad_state).

<mad-form submit="onSave">
    <mad-form-section :title="__('admin.user_data')" icon="user">
        {{-- campos principais, sempre visiveis --}}
    </mad-form-section>

    @if(!$that->isRowAttach())
        {{-- pesado/secundario: so na cortina ou na pagina --}}
        <mad-tabs> ... </mad-tabs>
    @endif

    <mad-btn variant="primary" type="submit" icon="save">Salvar</mad-btn>
</mad-form>

O onSave nao muda:

return (new MadResponse())
    ->toast(__('admin.user_saved'), 'success')
    ->closeDrawer()                            // fecha a attach-row (interceptado)
    ->manageRow($user->id, UserList::class);   // atualiza a linha

Mecanica

  1. Compile-time — MadGridCompiler::buildNavConfig() ve row e emite 'navRow' => true no actConfig.
  2. Hidratacao — MadDataGrid::_actFromConfig() chama GridAction::row().
  3. Emissao — MadAction::onRowAttach() gera onclick="Mad.rowAttach(this, 'UserForm@onEdit', {id:2}, '/app/usuarios/2/editar')"; a URL amigavel vem assada do PHP.
  4. Client — Mad.rowAttach() em mad.js acha o tr.mad-dg-row, faz o GET com os headers X-Mad-Partial: 1 e X-Mad-Row-Attach: 1, insere <tr class="mad-dg-attach-row" data-attach-for="{rowId}"> com <td colspan> e reidrata (_madRewriteAlpineAttrs antes de Mad._reinit).
  5. Server — o header X-Mad-Row-Attach faz _wrapRenderedHtml() devolver o componente cru, sem o chrome de drawer/modal. Permissoes: caminho identico ao do drawer.
  6. Save — o op close_overlay do closeDrawer() e interceptado no mad-livewire.js: se o wrapper esta dentro de tr.mad-dg-attach-row, remove a <tr>; senao dispara o evento maddrawer normal.

CSS em mad-ui.css: .mad-dg-attach-row (fundo color-mix com --mad-primary, sem zebra/hover), .mad-dg-attach-row > td (border-left de 3px), .mad-dg-attach-wrap (slide-down 0.18s), .mad-dg-attach-close, .mad-dg-attach-body. Dark mode coberto.

Comportamentos definidos

Situacao Comportamento
Clicar no lapis com o form ja aberto toggle: fecha
Abrir outra linha single-open: fecha a anterior
Botao X do chrome fecha no client, sem round-trip
Save ok toast + attach fecha + linha atualiza com highlight (manage_row)
Erro de validacao modal de erros; a attach permanece aberta e compacta
Card-view (sem <tr>) fallback para Mad.get — abre drawer normal
Sort, filtro, paginacao, busca full re-render da grid descarta a attach-row
Campos fora da view compacta seguem no state do form e sao re-gravados intactos no save

Gotchas

  • Os POSTs do MadWire nao reenviam o header X-Mad-Row-Attach; por isso o flag _rowAttach e detectado no show() e persistido no mad_state. Se voce reimplementar o state do componente, preserve essa entrada ou o re-render de validacao volta ao layout completo dentro da linha.
  • Nao gere row em grids que rodam primariamente em card-view: o fallback funciona, mas o resultado sera drawer de qualquer forma.
  • Re-render completo da grid descarta a attach-row com edicoes nao salvas — sem confirmacao de descarte (limitacao conhecida da v1).
  • Nao ha animacao de saida; a remocao e imediata.
  • Alternativa para forms grandes com regras proprias: um XxxQuickForm dedicado apontado pelo <mad-nav row>, herdando permissao via MadRoutes::expose(['permissionFrom' => ...]).