Docs›Componentes (Admin)›mad-gantt-column — mapping + render
Componentes (Admin)

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 "atributo name-field em 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 (hidden ausente): mapeia e vira coluna na sidebar.
  • hidden: só mapeia (ex: progress, parentId, phase, milestone que 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: GanttTask tem coluna name, start, …), omita source — ele assume = field.

Regras

  • Largura da sidebar = soma das larguras visíveis — dispensa task-col-width.
  • field="duration" é calculado de start/end (não tem source, não mapeia coluna).
  • Sem nenhuma coluna tree → a primeira visível vira a árvore.
  • hidden não conta pra largura nem renderiza — só alimenta o mapping.
  • Atributos *-field na 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 *Field props → mapTask produz o shape da barra.
  • JS: sidebar.js itera cfg.columns visíveis e desenha cada célula (a tree ganha indent + caret; owner vira 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 → mapTask emitiu phase_id, parentId, progress, milestone, start, owner — mapping derivado das colunas.
  • cfg.columns carrega source + hidden.
  • client (bundle real em node): head só com colunas visíveis (is-tree na árvore), corpo iterando colunas (caret+nome na árvore, duration→Nd, avatares no owner), colunas hidden ausentes do DOM.
  • php -l + node --check limpos; JSON schema do gantt-builder.md válido.