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
- Compile-time —
MadGridCompiler::buildNavConfig()verowe emite'navRow' => trueno actConfig. - Hidratacao —
MadDataGrid::_actFromConfig()chamaGridAction::row(). - Emissao —
MadAction::onRowAttach()geraonclick="Mad.rowAttach(this, 'UserForm@onEdit', {id:2}, '/app/usuarios/2/editar')"; a URL amigavel vem assada do PHP. - Client —
Mad.rowAttach()emmad.jsacha otr.mad-dg-row, faz o GET com os headersX-Mad-Partial: 1eX-Mad-Row-Attach: 1, insere<tr class="mad-dg-attach-row" data-attach-for="{rowId}">com<td colspan>e reidrata (_madRewriteAlpineAttrsantes deMad._reinit). - Server — o header
X-Mad-Row-Attachfaz_wrapRenderedHtml()devolver o componente cru, sem o chrome de drawer/modal. Permissoes: caminho identico ao do drawer. - Save — o op
close_overlaydocloseDrawer()e interceptado nomad-livewire.js: se o wrapper esta dentro detr.mad-dg-attach-row, remove a<tr>; senao dispara o eventomaddrawernormal.
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_rowAttache detectado noshow()e persistido nomad_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
rowem 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
XxxQuickFormdedicado apontado pelo<mad-nav row>, herdando permissao viaMadRoutes::expose(['permissionFrom' => ...]).