Makuco UI
ComponentesData Display

Datagrid

Grid de dados interativo (`mk-datagrid`) com ordenação, paginação, colunas fixas, trocadas e redimensionadas, virtualização, células customizadas, edição, editor de opções, preenchimento para baixo e para cima, linhas expansíveis e seleção.

O mk-datagrid exibe e opera grandes volumes de dados tabulares: ordenação, paginação, colunas fixas, ocultas, trocadas e redimensionadas, virtualização, células customizadas, estados vazio e carregando, edição (texto, máscara e opções), preenchimento para baixo e para cima, linhas expansíveis e seleção de linhas. A navegação segue o padrão grid da WAI-ARIA APG, com uma única parada de Tab e setas entre as células. Para tabelas estáticas e pequenas, use o Table.

Padrão

columns e rows são arrays. Cada linha precisa de um identificador estável, lido por rowKey (padrão "id"). O grid nunca altera rows: toda mudança de dado é emitida como evento e aplicada pelo consumidor.

import { MkDatagrid, type MkDatagridColumn } from '@db1/makuco-ui-react';

const columns: MkDatagridColumn<Pessoa>[] = [
  { key: 'nome', label: 'Nome', sortable: true, rowHeader: true },
  { key: 'cargo', label: 'Cargo', sortable: true },
  { key: 'unidade', label: 'Unidade' },
  { key: 'email', label: 'E-mail', width: 240 },
];

<MkDatagrid caption="Pessoas" columns={columns} rows={pessoas} />
import { MK_DATAGRID } from '@db1/makuco-ui-angular';
import { defineColumns } from '@db1/makuco-ui-core';

@Component({
  imports: [MK_DATAGRID],
  template: `<mk-datagrid caption="Pessoas" [columns]="columns" [rows]="pessoas"></mk-datagrid>`,
})
export class PessoasComponent {
  columns = defineColumns<Pessoa>([
    { key: 'nome', label: 'Nome', sortable: true, rowHeader: true },
    { key: 'cargo', label: 'Cargo', sortable: true },
    { key: 'unidade', label: 'Unidade' },
    { key: 'email', label: 'E-mail', width: 240 },
  ]);
  pessoas: Pessoa[] = [];
}

rowKey aceita o nome do campo ou uma função (row) => string. Quando não resolve um valor, o grid usa o índice da linha e avisa em desenvolvimento.

Tipos das linhas e colunas

rows aceita interface e type. As colunas tipadas pela linha (accessor, editable.options e fillable.formula recebem TRow) são declaradas com o tipo exportado: MkDatagridColumn<TRow>[] no React (acrescenta cell) e DatagridColumn<TRow>[] no Angular e em JS puro. defineColumns<TRow>([...]) é um atalho equivalente.

import { MkDatagrid, type MkDatagridColumn } from '@db1/makuco-ui-react';

interface Pessoa { id: string; nome: string; salario: number }

const columns: MkDatagridColumn<Pessoa>[] = [
  { key: 'nome', label: 'Nome' },
  { key: 'salario', label: 'Salário', accessor: (pessoa) => brl(pessoa.salario) },
];

<MkDatagrid caption="Pessoas" columns={columns} rows={pessoas} />
import { defineColumns } from '@db1/makuco-ui-core';

interface Pessoa { id: string; nome: string; salario: number }

columns = defineColumns<Pessoa>([
  { key: 'nome', label: 'Nome' },
  { key: 'salario', label: 'Salário', accessor: (pessoa) => brl(pessoa.salario) },
]);

Regra de controle

A regra vale para as sete props de estado (sorting, page, pageSize, expandedRows, selectedRows, columnOrder, columnWidths): com um valor (inclusive []), o estado é controlado; com null ou undefined, o grid controla o estado, o que cobre o | async do Angular antes do primeiro valor. Ao voltar a null depois de controlada, o grid continua do último valor controlado, como estado interno. Cada evento traz o estado resultante no tipo da prop.

PropEventoEstado no evento
sortingmkSortChangedetail.sorting
pagemkPageChangedetail.page
pageSizemkPageSizeChangedetail.pageSize
expandedRowsmkRowExpanddetail.expandedRows
selectedRowsmkSelectionChangedetail.selectedRows
columnOrdermkColumnOrderChangedetail.columnOrder
columnWidthsmkColumnWidthsChangedetail.columnWidths
const [selectedRows, setSelectedRows] = useState<string[]>([]);

<MkDatagrid
  caption="Pessoas"
  columns={columns}
  rows={pessoas}
  selectable
  selectedRows={selectedRows}
  onMkSelectionChange={({ detail }) => setSelectedRows(detail.selectedRows)}
/>
selectedRows$ = new BehaviorSubject<string[] | null>(null);
<mk-datagrid
  caption="Pessoas"
  [columns]="columns"
  [rows]="pessoas"
  [selectable]="true"
  [selectedRows]="selectedRows$ | async"
  (mkSelectionChange)="selectedRows$.next($event.detail.selectedRows)"
></mk-datagrid>

Opções de coluna

  • rowHeader marca as células da coluna com role="rowheader": elas nomeiam a linha para leitores de tela e para o rótulo do botão de expandir.
  • helperText mostra o ícone de ajuda no cabeçalho, com tooltip no hover e no foco.
  • align alinha conteúdo e cabeçalho (start, center, end). Use end para números.
  • accessor calcula o valor de colunas sem campo nos dados ou derivadas. Ele é o valor usado na ordenação.
  • hidden: true oculta a coluna. Para alternar, passe um novo array de columns.
const columns: MkDatagridColumn<Pessoa>[] = [
  { key: 'nome', label: 'Nome', rowHeader: true },
  { key: 'salario', label: 'Salário', align: 'end', helperText: 'Valor bruto mensal', accessor: (p) => brl(p.salario) },
];
columns = defineColumns<Pessoa>([
  { key: 'nome', label: 'Nome', rowHeader: true },
  { key: 'salario', label: 'Salário', align: 'end', helperText: 'Valor bruto mensal', accessor: (p) => brl(p.salario) },
]);

Ordenação

sortable na coluna ordena localmente. sorting é uma lista de DatagridSort ({ columnKey, direction }, hoje uma entrada só): com ela, o grid emite mkSortChange e espera a prop mudar, e [] é controlado sem ordenação. detail.sorting traz a ordenação resultante, pronta para voltar à prop. Com manualSorting, o grid não reordena as linhas, para a ordenação no servidor.

A regra de controle está em Regra de controle.

import type { DatagridSort } from '@db1/makuco-ui-core';
import { MkDatagrid } from '@db1/makuco-ui-react';

const [sorting, setSorting] = useState<DatagridSort[]>([]);

<MkDatagrid
  caption="Pessoas"
  columns={columns}
  rows={rows}
  manualSorting
  sorting={sorting}
  onMkSortChange={({ detail }) => setSorting(detail.sorting)}
/>
<mk-datagrid
  caption="Pessoas"
  [columns]="columns"
  [rows]="rows"
  [manualSorting]="true"
  [sorting]="sorting"
  (mkSortChange)="sorting = $event.detail.sorting"
></mk-datagrid>

Colunas fixas, zebrado e destaque

pinned: "start" ou "end" mantém a coluna visível na rolagem horizontal. striped alterna o fundo a partir da 1ª linha. highlightedRows destaca linhas por rowId ou por predicado.

mkRowClick dispara no clique na linha, exceto quando o clique nasce num conteúdo interativo da célula: controle nativo, elemento com papel de controle, host com focável no shadow aberto (como mk-button) ou elemento com data-mk-no-row-click.

Os exemplos completos em React e Angular estão no Storybook.

Larguras e quebra de linha

width fixa a largura em px. Colunas sem width dividem o espaço livre na proporção de flex (padrão 1), sem ficar abaixo de minWidth (padrão 120 px). O texto longo termina em reticências; wrap: true quebra o texto da coluna e deixa a linha crescer, também com virtual.

const columns = [
  { key: "nome", label: "Nome", width: 180 },
  { key: "descricao", label: "Descrição", flex: 2, minWidth: 240, wrap: true },
  { key: "cidade", label: "Cidade" },
];

Células customizadas

Em React, cell na coluna renderiza o conteúdo por portal na mesma árvore React: contexto, hooks e Providers funcionam. Também é possível declarar <MkDatagridCell name="status"> como filho e apontar template: "status" na coluna. Com React.lazy e Suspense, o registro de um MkDatagridCell pode levar mais de um frame, e o aviso de template ausente pode aparecer nesse intervalo.

Em Angular, use ng-template[mkDatagridCell] com o mesmo nome de column.template. Sem [inferRow], let-row é any; com as linhas no input, ganha o tipo delas.

Os wrappers montam um componente ou uma view por célula visível e não reaproveitam conteúdo entre linhas.

Em JavaScript sem framework, renderTemplate(name, ctx, container) monta o conteúdo no contêiner e pode devolver { update, destroy, recycle }.

Os exemplos completos em React e Angular estão no Storybook.

Cabeçalho customizado

headerTemplate na coluna indica o conteúdo do cabeçalho; sem ele, o cabeçalho mostra label. O template ocupa só a área do rótulo: ordenação, ajuda, troca e redimensionamento continuam do grid. O contexto traz label, columnKey, columnIndex, align e sort, sem row.

import { MkDatagrid, MkIcon, type MkDatagridColumn } from '@db1/makuco-ui-react';

const columns: MkDatagridColumn<Pedido>[] = [
  {
    key: 'entrega',
    label: 'Entrega',
    sortable: true,
    header: ({ label }) => (
      <>
        <MkIcon name="calendar" size="sm" /> {label}
      </>
    ),
  },
];

<MkDatagrid caption="Pedidos" columns={columns} rows={pedidos} />

Para reaproveitar o template em várias colunas, use headerTemplate: 'comIcone' na coluna e <MkDatagridHeader name="comIcone">{(ctx) => ...}</MkDatagridHeader> como filho do grid.

import { MK_DATAGRID, MkIcon } from '@db1/makuco-ui-angular';
import { defineColumns } from '@db1/makuco-ui-core';

@Component({
  imports: [MK_DATAGRID, MkIcon],
  template: `
    <mk-datagrid caption="Pedidos" [columns]="columns" [rows]="pedidos">
      <ng-template mkDatagridHeader="comIcone" let-label="label">
        <mk-icon name="calendar" size="sm"></mk-icon> {{ label }}
      </ng-template>
    </mk-datagrid>
  `,
})
export class PedidosComponent {
  columns = defineColumns<Pedido>([
    { key: 'entrega', label: 'Entrega', sortable: true, headerTemplate: 'comIcone' },
  ]);
  pedidos: Pedido[] = [];
}
  • O nome acessível do cabeçalho é sempre o label. Um número no template (como o 3 de um badge) não é anunciado no columnheader: use helperText ou mostre o dado nas células.
  • Um controle no template (como um botão de filtro) não ordena a coluna ao ser clicado. Enter ou F2 no cabeçalho entra nos controles e Esc volta.
  • O conteúdo do template é uma linha flex centralizada na vertical: ícone, chip e texto ficam no mesmo eixo do handle, da ajuda e do botão de ordenação. Conteúdo mais largo que a coluna é cortado, sem reticências, e os botões de ajuda e de ordenação continuam visíveis.
  • As colunas de seleção e de expansão não aceitam template de cabeçalho.

Exemplos com contador, filtro rápido e sort do contexto estão no Storybook.

Altura das linhas

Por padrão, a linha do corpo tem no mínimo --mk-datagrid-row-height (44 px) e cresce com o conteúdo: colunas com wrap, templates de célula mais altos, editores. Sem conteúdo alto, a linha continua com 44 px. rowHeight fixa a altura de toda linha do corpo, em px: o conteúdo que não cabe é cortado e wrap não tem efeito. O cabeçalho mantém a altura nos dois casos.

<MkDatagrid virtual rowHeight={36} columns={columns} rows={rows} />
<mk-datagrid virtual [rowHeight]="36" [columns]="columns" [rows]="rows"></mk-datagrid>

Virtualização

virtual monta só as linhas visíveis e mede cada uma: wrap e templates altos funcionam, e --mk-datagrid-row-height é a estimativa das linhas ainda não medidas. Em listas muito grandes com conteúdo uniforme, rowHeight dispensa a medição e dá a rolagem mais precisa. O grid ocupa a altura do pai; sem altura no pai, usa --mk-datagrid-height ou 480 px. As linhas fora da janela não estão no DOM; aria-rowcount e aria-rowindex informam o total e a posição real.

Os exemplos completos em React e Angular estão no Storybook.

Paginação no servidor

pagination mostra o mk-pagination abaixo do grid e fatia rows localmente (25 por página). Com manualPagination e totalItems, rows é a página vinda do servidor; page e pageSize controlam a posição. Com loading, a página vira linhas de skeleton na mesma quantidade, e a paginação fica desabilitada.

<MkDatagrid
  caption="Pessoas"
  columns={columns}
  rows={pagina}
  loading={loading}
  pagination
  manualPagination
  page={page}
  pageSize={pageSize}
  totalItems={total}
  pageSizeOptions={[10, 25, 50]}
  onMkPageChange={({ detail }) => carregar(detail.page, pageSize)}
  onMkPageSizeChange={({ detail }) => carregar(1, detail.pageSize)}
/>
<mk-datagrid
  caption="Pessoas"
  [columns]="columns"
  [rows]="pagina"
  [loading]="loading"
  [pagination]="true"
  [manualPagination]="true"
  [page]="page"
  [pageSize]="pageSize"
  [totalItems]="total"
  [pageSizeOptions]="[10, 25, 50]"
  (mkPageChange)="carregar($event.detail.page, pageSize)"
  (mkPageSizeChange)="carregar(1, $event.detail.pageSize)"
></mk-datagrid>

Vazio e carregando

Sem linhas e sem loading, o grid mostra o mk-empty. Com loading, com ou sem dados anteriores, o corpo mostra linhas de mk-skeleton na proporção da tabela: as linhas da página (ou as que estavam na tela), as colunas visíveis com a largura, o alinhamento e a fixação de cada uma, e o skeleton de texto com 50% a 90% da célula. O cabeçalho continua visível; ordenação, paginação e teclado ficam bloqueados. Os slots empty e loading substituem o estado vazio e as linhas de skeleton.

<MkDatagrid caption="Pessoas" columns={columns} rows={[]} loading={loading}>
  <MkEmpty slot="empty">
    <MkEmptyTitle>Nenhuma pessoa encontrada</MkEmptyTitle>
  </MkEmpty>
</MkDatagrid>
<mk-datagrid caption="Pessoas" [columns]="columns" [rows]="[]" [loading]="loading">
  <mk-empty slot="empty">
    <mk-empty-title>Nenhuma pessoa encontrada</mk-empty-title>
  </mk-empty>
</mk-datagrid>

Edição e preenchimento

editable mostra um campo sempre visível na célula, no visual do mk-table-input. Enter ou sair do campo confirma, Esc desfaz. A confirmação emite mkCellChange, e o consumidor aplica o valor em rows; sem isso, o campo volta ao valor de rows.

O valor emitido tem o tipo do valor original da linha. Com máscara numérica (number, brl), o valor é em unidades, como no mk-input-number: preco: 14.9 aparece como R$ 14,90 e emite 15.9 ao digitar R$ 15,90. Campo vazio emite null. O mk-table-input avulso usa as mesmas unidades, mas sempre como string ("15.90"). Texto que não converte não emite e marca o campo com aria-invalid.

fillable numa coluna editable replica o valor para as linhas abaixo ou acima: arrastando o quadrado de 8 × 8 px (--db1-spacing-2) que a célula ativa mostra centrado no canto inferior direito, metade para fora dela (cursor em cruz), para baixo ou para cima, ou com Shift+↓/Shift+↑ (estende o intervalo) e Ctrl+D (preenche). O grid emite mkFill com direction ('down' ou 'up'), e cada linha de destino traz o value já calculado, da origem para fora.

Editor sob medida

editable.template monta um editor próprio no lugar do campo, pelo contrato de template: o contexto recebe ctx.commit(value) e ctx.cancel(). Em React e Angular, o editor é um template de célula com o nome em editable.template. Para escolher entre opções, o editor de opções tem o visual da grid; use editable.template para componentes que ele não cobre.

Modos de preenchimento

fillable: true copia o valor da origem. Um objeto escolhe o modo: { mode: 'series' } continua número, data ISO (AAAA-MM-DD) ou Date (um dia por linha) e texto com número no fim ("Lote 001"), com passo +1 para baixo e −1 para cima; { formula } calcula cada linha de destino por uma função síncrona, da origem para fora (previous é a linha mais perto da origem).

formula recebe { source, previous, index, direction, row, rowId, columnKey } e devolve o valor da célula; undefined deixa a linha de fora, e uma exceção cancela o preenchimento. direction ('down' ou 'up') permite uma progressão espelhada: ({ previous, direction }) => direction === 'up' ? previous / 1.1 : previous * 1.1.

Editor de opções

editable.options mostra o campo da grid com um chevron no fim. A linha guarda o value da opção e o campo mostra o label (optionValue e optionLabel trocam os campos lidos). As opções são uma lista fixa ou uma função (row) => SelectOption[], chamada com a linha atual.

  • Digitar filtra as opções pelo label, sem acento e sem diferenciar maiúscula, e destaca o primeiro resultado.
  • ↓ abre a lista com o valor atual destacado; Enter, Tab ou o clique confirmam a opção. O chevron abre e fecha a lista.
  • Ao sair do campo, um texto igual a um label confirma essa opção e o campo vazio confirma null.
  • Um texto sem opção correspondente não emite mkCellChange: a célula mostra o anel de erro até a escolha de uma opção ou o Esc.
  • Esc com a lista aberta fecha a lista; com ela fechada, volta ao valor de rows.
  • Com fillable, o valor da origem é copiado, e a linha em que ele não está entre as opções fica de fora de targets.

Os exemplos completos em React e Angular estão no Storybook.

Linhas expansíveis

O conteúdo expandido dá à primeira coluna um botão de expandir. Em React, use renderExpanded; em Angular, <ng-template mkDatagridExpand>. expandedRows controla as linhas expandidas, e mkRowExpand informa cada mudança com o conjunto resultante em detail.expandedRows.

Os exemplos completos em React e Angular estão no Storybook.

Seleção de linhas

selectable adiciona a coluna de checkbox no início do grid. O checkbox do cabeçalho marca as linhas selecionáveis da página atual. selectedRows guarda os rowIds e controla a seleção; rowSelectable desabilita linhas. mkSelectionChange traz o conjunto resultante completo.

const [selecionadas, setSelecionadas] = useState<string[]>([]);

<MkDatagrid
  caption="Pessoas"
  columns={columns}
  rows={pessoas}
  selectable
  selectedRows={selecionadas}
  rowSelectable={(row) => row.status === 'Ativo'}
  onMkSelectionChange={(e) => setSelecionadas(e.detail.selectedRows)}
/>
<mk-datagrid
  caption="Pessoas"
  [columns]="columns"
  [rows]="pessoas"
  [selectable]="true"
  [selectedRows]="selecionadas"
  [rowSelectable]="ativa"
  (mkSelectionChange)="selecionadas = $event.detail.selectedRows"
></mk-datagrid>

Troca de colunas

reorderable mostra um handle no início do cabeçalho. Arrastar o handle até outro cabeçalho troca as posições das duas colunas, dentro do mesmo grupo de fixação; uma coluna sem outra coluna visível para trocar no grupo não mostra o handle. columnOrder controla a ordem e mkColumnOrderChange informa cada troca. Por teclado, Enter no cabeçalho (F2 em colunas ordenáveis) leva ao handle, e ←/→ trocam com a vizinha.

Os exemplos completos em React e Angular estão no Storybook.

Redimensionar colunas

resizable mostra um separador na borda final do cabeçalho. A largura respeita minWidth e maxWidth da coluna; duplo clique restaura. mkColumnResize informa cada frame do arrasto, e mkColumnWidthsChange informa o conjunto final. Em Angular, mkColumnResize dispara change detection a cada frame: ouça só mkColumnWidthsChange ou use runOutsideAngular.

Os exemplos completos em React e Angular estão no Storybook.

O grid segue o padrão grid da APG e tem dois modos.

  • Navegação: uma única parada de Tab. A célula ativa é a única com tabindex="0" (roving tabindex), as setas a movem e a linha de cabeçalho faz parte do percurso. Os focáveis dentro das células saem da ordem de Tab.
  • Interação: Enter ou F2 foca o conteúdo da célula (um botão, um link, o campo editável). Esc, ou Tab no último focável, volta à navegação.

Digitar numa célula editável começa a edição substituindo o valor.

TeclaComportamento
TabEntra no grid pela célula ativa; sai do grid na próxima tecla Tab.
← → ↑ ↓Move a célula ativa. ↑ na primeira linha vai para o cabeçalho.
Home / EndPrimeira / última célula da linha.
Ctrl+Home / Ctrl+EndPrimeira / última célula do grid.
PageUp / PageDownUma página visível acima / abaixo.
Enter / Espaço no cabeçalhoAlterna a ordenação.
Enter no cabeçalho sem ordenação / F2Foco no handle ou no separador. Esc volta ao cabeçalho.
← → no handleTroca a coluna com a vizinha válida do mesmo grupo (em RTL, ← vai para a direita).
← → (Shift: 32 px) / Home / End no separadorAjusta a largura em 8 px / mínimo / máximo.
Espaço

Com selectable, alterna a seleção da linha ativa; no cabeçalho do checkbox, alterna o selecionar todas.

Enter / F2Entra no conteúdo da célula ou no campo editável.
Digitar numa célula editávelComeça a edição substituindo o valor.
↓ / ↑ no editor de opções↓ abre a lista com o valor atual destacado; ↓ e ↑ movem o destaque.
Enter / Tab no editor de opçõesConfirmam a opção destacada; Tab segue a navegação.
EscVolta à navegação; num campo, desfaz a edição.
Shift+↓ ou Shift+↑ / Ctrl+DEstende o intervalo para baixo ou para cima / preenche (colunas fillable).

Props — mk-datagrid

PropTipoPadrãoDescrição
columnsDatagridColumn[][]Definição das colunas (tabela abaixo).
rowsDatagridRow[][]Linhas de dados.
rowKeystring | (row) => string"id"Identificador estável da linha.
captionstring—Nome acessível do grid.
virtualbooleanfalseVirtualiza as linhas: só as visíveis ficam montadas, cada uma medida.
rowHeightnumber—Altura fixa das linhas do corpo, em px. Omitida, a linha tem no mínimo --mk-datagrid-row-height e cresce com o conteúdo. Definida, o conteúdo é cortado e wrap não tem efeito.
stripedbooleanfalseZebrado a partir da 1ª linha.
highlightedRowsstring[] | (row) => boolean—Linhas destacadas, por rowId ou predicado.
sortingDatagridSort[] | null—Ordenação controlada; [] sem ordenação, null interno.
manualSortingbooleanfalseNão reordena as linhas, para a ordenação no servidor.
loadingbooleanfalseTroca as linhas por linhas de skeleton na proporção da tabela e bloqueia a interação.
paginationbooleanfalseMostra o mk-pagination integrado.
pagenumber | null—Página atual (a partir de 1), controlada; null interno.
pageSizenumber | null—Linhas por página, controlada; null interno (25).
pageSizeOptionsnumber[]—Opções de tamanho de página.
totalItemsnumber—Total de linhas no servidor, com manualPagination.
manualPaginationbooleanfalseO grid não fatia rows, só emite os eventos.
expandTemplatestring—Template do conteúdo expandido (JS). Em React, renderExpanded; em Angular, ng-template[mkDatagridExpand].
expandedRowsstring[] | null—Linhas expandidas, controlada; null interno.
selectablebooleanfalseAdiciona a coluna de checkbox (fixada no início, fora de columns).
selectedRowsstring[] | null—rowIds selecionados, controlada (inclusive []). null ou undefined: o grid controla a seleção.
rowSelectable(row) => boolean—false desabilita o checkbox da linha e a tira do selecionar todas.
reorderablebooleanfalseHandle de troca em todas as colunas (column.reorderable sobrescreve).
resizablebooleanfalseSeparador de redimensionamento em todas as colunas (column.resizable sobrescreve).
columnOrderstring[] | null—Ordem das chaves de columns, controlada. null ou undefined: interna.
columnWidthsRecord<string, number> | null—Larguras em px por chave, controlada. null ou undefined: interna.
renderTemplateDatagridTemplateRenderer—Monta as células customizadas (JS). Os wrappers o preenchem.
renderHeaderTemplateDatagridHeaderTemplateRenderer—Monta o conteúdo do cabeçalho das colunas com headerTemplate (JS). Os wrappers o preenchem.
renderExpanded(ctx) => ReactNode—Só React: conteúdo da linha expandida, no lugar de expandTemplate.

Props — coluna (DatagridColumn)

PropTipoPadrãoDescrição
keystring—Identificador e, sem accessor, campo lido na linha.
labelstring—Texto do cabeçalho.
accessor(row) => unknown—Valor de colunas derivadas.
widthnumber—Largura fixa em px.
flexnumber1Peso na divisão do espaço livre.
minWidthnumber120Largura mínima: piso das colunas flexíveis e do redimensionamento.
maxWidthnumber—Largura máxima: teto do redimensionamento e da divisão flexível.
reorderablebooleanherda do gridHandle de troca no cabeçalho.
resizablebooleanherda do gridSeparador de redimensionamento.
align"start" | "center" | "end""start"Alinhamento do conteúdo e do cabeçalho.
wrapbooleanfalseQuebra o texto e deixa a linha crescer. Sem efeito com rowHeight.
sortablebooleanfalseHabilita a ordenação.
pinned"start" | "end"—Fixa a coluna na rolagem horizontal.
hiddenbooleanfalseOculta a coluna.
helperTextstring—Texto de ajuda no cabeçalho.
rowHeaderbooleanfalseCélulas com role="rowheader".
templatestring—Nome do template da célula.
headerTemplatestring—Nome do template do conteúdo do cabeçalho. Sem ele, o cabeçalho mostra label. Em React, header; em Angular, ng-template[mkDatagridHeader].
cell(ctx) => ReactNode—Só React: conteúdo da célula.
header(ctx) => ReactNode—Só React: conteúdo do cabeçalho.
editabletrue | { mask, placeholder, template, options, optionValue, optionLabel }—Campo editável na célula. Com options, editor de opções.
fillableboolean | { mode?, formula? }falsePreencher para baixo ou para cima: copia, continua a série (mode: 'series') ou calcula por formula. Exige editable.

Inputs das diretivas Angular

PropTipoPadrãoDescrição
mkDatagridCellstring—Nome do template, o mesmo de column.template.
mkDatagridHeaderstring—Nome do template do cabeçalho, o mesmo de column.headerTemplate.
inferRow (em mkDatagridCell)TRow[]—

Só para tipagem: com as linhas aqui, let-row ganha o tipo delas. Sem ele, let-row é any.

inferRow (em mkDatagridExpand)TRow[]—Só para tipagem do let-row em ng-template[mkDatagridExpand].

Eventos

EventoComponentePayloadDescrição
mkSortChangemk-datagrid{ columnKey, direction, sorting }A ordenação muda. direction: "none", "ascending" ou "descending"; sorting é a ordenação resultante ([] sem ordenação).
mkRowClickmk-datagrid{ rowId, row, originalEvent }Clique na linha, exceto em conteúdo interativo da célula.
mkPageChangemk-datagrid{ page }Troca de página.
mkPageSizeChangemk-datagrid{ pageSize }Troca do tamanho de página.
mkActiveCellChangemk-datagrid{ rowId, columnKey }A célula ativa muda.
mkCellChangemk-datagrid{ rowId, columnKey, value, previousValue }Edição confirmada com valor diferente.
mkFillmk-datagrid{ source, targets, value, direction }Preenchimento para baixo ou para cima (direction: 'down' | 'up'). Cada item de targets traz { rowId, value } com o valor calculado, da origem para fora.
mkRowExpandmk-datagrid{ rowId, expanded, expandedRows }Linha expandida ou recolhida; expandedRows é o conjunto resultante.
mkColumnOrderChangemk-datagrid{ columnOrder, source, target }Duas colunas trocam de lugar.
mkColumnResizemk-datagrid{ columnKey, width }Largura provisória a cada frame do arrasto (informativo).
mkColumnWidthsChangemk-datagrid{ columnWidths, columnKey, width }Ao soltar, restaurar (duplo clique) e a cada passo de teclado.
mkSelectionChangemk-datagrid{ selectedRows, rowIds, selected }A seleção muda. rowIds são as linhas afetadas (uma na alternância, as da página no selecionar todas) e selected o estado aplicado a elas.

focusCell(rowId, columnKey) rola até a célula, monta a linha se preciso e a foca. Use para devolver o foco depois de fechar um dialog aberto pela célula.

scrollToRow(rowId) rola até a linha sem mover o foco e devolve false quando ela não está entre as linhas exibidas. getState() devolve o estado atual das sete props de estado (sorting, page, pageSize, selectedRows, expandedRows, columnOrder, columnWidths), controladas ou internas, para salvar a visão do usuário e devolvê-la às props depois.

applyCellChange(rows, detail, rowKey?) e applyFill(rows, detail, rowKey?), exportadas por @db1/makuco-ui-core, aplicam o mkCellChange e o mkFill em rows e devolvem um novo array. Elas localizam a linha pela mesma regra do grid (rowKey, padrão "id").

Os eventos dos componentes internos do grid (mk-pagination e cabeçalhos) não saem pelo host. O mkOpen e o mkClose do mk-menu não borbulham: o grid os escuta na fase de captura para elevar a célula fixa com menu aberto, e um ancestral que queira escutá-los usa { capture: true }.

Slots

ComponenteSlotDescrição
mk-datagridemptySubstitui o estado vazio padrão.
mk-datagridloadingSubstitui as linhas de skeleton do estado carregando.

CSS Custom Properties

PropriedadePadrãoDescrição
--mk-datagrid-row-height44px

Altura mínima das linhas do corpo e altura do cabeçalho; no modo virtual, estimativa das linhas ainda não medidas. Com rowHeight, a prop define a altura do corpo.

--mk-datagrid-heightaltura do pai, ou 480pxAltura do grid virtual quando o pai não tem altura.

Acessibilidade

  • role="grid" com aria-label vindo de caption, aria-rowcount e aria-colcount. Cada linha tem aria-rowindex com a posição real, inclusive com virtual.
  • Cabeçalhos ordenáveis expõem aria-sort, e o botão de ordenar tem o rótulo "Ordenar por {coluna}".
  • Com selectable, o grid tem aria-multiselectable="true" e cada linha tem aria-selected. A coluna do checkbox tem a chave __select (DATAGRID_SELECT_COLUMN_KEY), aceita em focusCell e mkActiveCellChange, e conta em aria-colindex e aria-colcount. Os checkboxes são nomeados "Selecionar linha {nome}" e "Selecionar todas as linhas da página", e a contagem é anunciada por role="status".
  • O handle de troca é um botão "Mover coluna {nome}" e o separador tem role="separator" com aria-valuenow, aria-valuemin e aria-valuemax. Ambos saem do Tab até o cabeçalho entrar em modo interação, e a troca é anunciada por role="status".
  • O editor de opções é um role="combobox" com aria-expanded, aria-controls (lista role="listbox") e aria-activedescendant; o foco fica no campo e o chevron é decorativo.
  • A zona de arrasto do preenchimento é decorativa (aria-hidden); a célula fillable ativa anuncia o atalho por aria-description ("Shift+seta para estender, Ctrl+D para preencher").
  • Células editáveis têm aria-readonly="false". O botão de expandir tem aria-expanded, aria-controls e o rótulo "Expandir {nome da linha}".
  • Com loading, o grid tem aria-busy="true", o corpo com os skeletons fica aria-hidden e o grid anuncia um único "Carregando…" por role="status".
  • Uma única parada de Tab (roving tabindex). Enter ou F2 entra no conteúdo da célula; Esc volta à navegação.
  • Foco por teclado com o anel padrão (--stroke-info) nas células sem campo e nos cabeçalhos; nas células editáveis (e nas com fill handle), o anel contorna a célula inteira, e o campo não desenha anel próprio.

Abaixo do AA:

  • Contraste do destaque: o destaque (highlightedRows) e a célula selecionada são indicados só pelo fundo: 1,38:1 contra a célula padrão na marca winner-box, e sem diferença visível na marca makuco até a revisão da paleta.
  • Pendência: no tema escuro, o anel de foco sobre a célula selecionada tem 2,57:1 por dentro. O token próprio do tema escuro está pendente.
  • Quadrado do preenchimento: no tema escuro, o quadrado (--stroke-info) tem de 1,02:1 a 2,01:1 contra os fundos da célula, em todas as marcas. O atalho de teclado anunciado na célula independe dele.

As teclas do grid estão em Navegação por teclado.

On this page