mad-gantt-column — mapping + render
Como a sub-tag <mad-gantt-column> declara field-mapping e renderização da sidebar numa tacada só.
Atualizado em 2026-05-29. Documenta uma mudança: a sub-tag
<mad-gantt-column>passou a declarar o field-mapping E o render da sidebar. Acabou a duplicação "atributoname-fieldem cima +<column>embaixo". Spec completa do componente:gantt-builder.md.
O problema (antes)
O mapeamento coluna-do-banco → barra ficava nos atributos da tag, e as colunas da sidebar eram outra declaração — o mesmo campo aparecia duas vezes:
{{-- ANTES: name/start/end declarados 2x --}}
<mad-gantt model="TarefaProjeto"
name-field="nome" start-field="dt_inicio" end-field="dt_fim"
progress-field="progresso_pct" task-col-width="500">
<mad-gantt-column field="name" label="Tarefa" tree />
<mad-gantt-column field="start" label="Início" format="date" />
<mad-gantt-column field="end" label="Fim" format="date" />
</mad-gantt>
Pior: as <mad-gantt-column> eram inertes no render (a sidebar tinha layout
fixo e ignorava width/format/colunas extras).
A solução (depois)
A coluna carrega field (chave canônica) + source (coluna do banco).
O componente deriva o field-mapping das colunas; a sidebar renderiza exatamente
as colunas visíveis. Sem *-field em cima, sem task-col-width.
{{-- DEPOIS: cada campo declarado 1x, na coluna --}}
<mad-gantt model="TarefaProjeto" database="mini_erp">
<mad-gantt-column field="name" source="nome" label="Tarefa" width="240" tree />
<mad-gantt-column field="start" source="dt_inicio" label="Início" width="100" format="date" />
<mad-gantt-column field="end" source="dt_fim" label="Fim" width="100" format="date" />
<mad-gantt-column field="duration" label="Dias" width="60" format="days" align="right" />
{{-- mapping-only: não renderiza, só mapeia --}}
<mad-gantt-column field="progress" source="progresso_pct" hidden />
<mad-gantt-column field="parentId" source="parent_id" hidden />
</mad-gantt>
Anatomia da coluna
| Atributo | O que é | Default |
|---|---|---|
field |
chave canônica (vocabulário da barra) | — (obrigatório) |
source |
coluna do banco que alimenta a chave | = field |
label |
texto do cabeçalho | label default da chave |
width |
largura px (e soma = largura da sidebar) | 120 |
format |
date | datetime | days | percent | null |
null |
tree |
coluna com indent + caret (a árvore/WBS) | false |
align |
left | center | right |
left |
hidden |
só mapeia — não renderiza na sidebar | false |
Os dois papéis de uma coluna
<mad-gantt-column field="start" source="dt_inicio" label="Início" format="date" />
└─ canônica └─ coluna banco └──── render da sidebar ────┘
└────────── mapping (banco → barra) ──────────┘
- Visível (
hiddenausente): mapeia e vira coluna na sidebar. hidden: só mapeia (ex:progress,parentId,phase,milestoneque você precisa mapear mas não quer exibir como coluna).
Chaves canônicas (field)
id, name, start, end, progress, parentId, owner, code, milestone, phase, color, type + duration (calculada). São as chaves do shape da barra (as
mesmas do MadGantt::recordToTask). O field aponta pra uma delas — nunca
pro nome do banco. O source é que carrega o nome do banco.
Exemplo de divergência canônico × banco:
field (canônico) |
source típico |
|---|---|
name |
nome |
start / end |
dt_inicio / dt_fim |
progress |
progresso_pct |
parentId |
parent_id |
owner |
owner_id |
phase |
fase_id |
Quando banco == canônico (ex:
GanttTasktem colunaname,start, …), omitasource— ele assume= field.
Regras
- Largura da sidebar = soma das larguras visíveis — dispensa
task-col-width. field="duration"é calculado destart/end(não temsource, não mapeia coluna).- Sem nenhuma coluna
tree→ a primeira visível vira a árvore. hiddennão conta pra largura nem renderiza — só alimenta o mapping.- Atributos
*-fieldna tag ainda funcionam e têm prioridade (override) sobre o que a coluna deriva — escape-hatch pra mapear algo sem criar coluna. - Mudou colunas? Limpe
tmp/blade-cache/*.bladec(compila no Blade).
Modelo convencional vs não-convencional
Convencional (GanttTask: colunas name/start/end/progress/parent_id/…) —
source quase nunca precisa:
<mad-gantt model="GanttTask" database="minierp">
<mad-gantt-column field="name" label="Tarefa" width="220" tree />
<mad-gantt-column field="code" label="Cód." width="70" />
<mad-gantt-column field="duration" label="Dias" width="50" format="days" align="right" />
<mad-gantt-column field="owner" source="owner_id" label="Resp." width="70" align="right" />
<mad-gantt-column field="start" hidden />
<mad-gantt-column field="end" hidden />
<mad-gantt-column field="progress" hidden />
<mad-gantt-column field="parentId" source="parent_id" hidden />
<mad-gantt-column field="phase" source="phase_id" hidden />
<mad-gantt-column field="milestone" hidden />
</mad-gantt>
Não-convencional (TarefaProjeto: nome/dt_inicio/…) — source em cada um
que diverge (ver exemplo no topo).
Como funciona por dentro
<mad-gantt-column> ──(MadGanttCompiler.extractAll)──► config['columns'] = [{field,source,...}]
│
┌─────────────────────────────────────────────────────┤
▼ (PHP, server) ▼ (JS, client)
MadGanttComponent._applyInlineConfig component.js
→ _deriveFieldMapFromColumns($cols, $config) → cfg.columns
seta nameField/startField/... = source → sidebar.render / renderHead
(a menos que o *-field venha explícito no config) itera colunas visíveis:
→ buildGantt → mapTask width/format/label/align/tree
usa os *Field props → shape canônico da barra (hidden = pula)
- PHP: as colunas viram os
*Fieldprops →mapTaskproduz o shape da barra. - JS:
sidebar.jsiteracfg.columnsvisíveis e desenha cada célula (atreeganha indent + caret;ownervira avatares;durationé calculada).
Arquivos: MadGanttCompiler.php, MadGanttComponent.php
(_deriveFieldMapFromColumns), MadGantt.php (columns()),
lib/mad/gantt/render/sidebar.js, lib/mad/gantt/core/component.js,
lib/mad/mad-gantt.css, bundle lib/mad/mad-gantt.js.
NUNCA fazer
{{-- ERRADO: duplicar — name-field em cima + coluna embaixo --}}
<mad-gantt name-field="nome" ...>
<mad-gantt-column field="name" source="nome" tree />
</mad-gantt>
{{-- CERTO: só a coluna (source carrega o banco) --}}
<mad-gantt model="...">
<mad-gantt-column field="name" source="nome" tree />
</mad-gantt>
{{-- ERRADO: field = nome do banco --}}
<mad-gantt-column field="dt_inicio" label="Início" />
{{-- CERTO: field = canônico, source = banco --}}
<mad-gantt-column field="start" source="dt_inicio" label="Início" format="date" />
{{-- ERRADO: setar task-col-width junto com colunas (a soma já manda) --}}
<mad-gantt task-col-width="500"> ...colunas... </mad-gantt>
{{-- CERTO: a largura da sidebar = soma das larguras visíveis --}}
{{-- ERRADO: source numa coluna calculada --}}
<mad-gantt-column field="duration" source="dias" />
{{-- CERTO: duration é derivada de start/end --}}
<mad-gantt-column field="duration" label="Dias" format="days" />
Verificação (o que foi testado)
- server: tag sem
*-field→mapTaskemitiuphase_id,parentId,progress,milestone,start,owner— mapping derivado das colunas. cfg.columnscarregasource+hidden.- client (bundle real em node): head só com colunas visíveis (
is-treena árvore), corpo iterando colunas (caret+nome na árvore,duration→Nd, avatares noowner), colunashiddenausentes do DOM. php -l+node --checklimpos; JSON schema dogantt-builder.mdválido.