Skip to main content
cngx-src documentation

CngxDataGridAccordion

ComponentPrimaryOnPushNo encapsulationv0.1.0WCAG AA

projects/ui/data-grid-accordion/data-grid-accordion.component.ts

Import#

import { CngxDataGridAccordion } from '@cngx/ui/data-grid-accordion'

Description#

Data-grid accordion group. A disclosure accordion whose header, rows, and footer all share one grid-template-columns contract, so N arbitrary cells align down the grid - the ceiling the accordion data-grid skin could never reach with its fixed three slots. Hosts the headless CngxAccordion brain via hostDirectives (so CNGX_ACCORDION and roving keyboard nav come with it), forwards [multi] and the controlled [(openIds)] model, publishes the column template onto the inherited --cngx-dga-columns property, and reflects [skin] onto [data-skin]. Projects its CngxDataGridHeader, CngxDataGridRows, and CngxDataGridFooter through a single <ng-content />; it owns no rendering beyond providing CNGX_DATA_GRID_ACCORDION so rows read the shared heading level.

It is a disclosure accordion, not a data grid: no role="grid", no cell edit, no selection model, no keyboard grid navigation. It hosts the orthogonal CngxSort atom as a second hostDirective and exposes it on CNGX_DATA_GRID_ACCORDION as sort, so header cells become sortable with one cngxDgaSortHeader attribute (no [cngxSortRef] plumbing) and a consumer can bind the controlled [sortActive] / [sortDirection] inputs and read (sortChange). For an uncontrolled grid that just needs a starting order, [initialSort]="{ active, direction }" seeds the sort once and then yields to header clicks. It hosts the orthogonal CngxFilter atom the same way, exposed as filter: [filterPredicate] forwards to its controlled predicate, (filterChange) re-emits, and a projected cngxDgaFilter input two-way-binds the simple [(filterTerm)]. The group only publishes sort/filter state - the consumer still derives the visible + ordered rows via a computed() and owns the @for; the open set is keyed by row value so a sorted or filtered row stays open while it moves.

The column widths are declared on the header cells via col (grow / fit / sm / md / lg); the group derives the shared template from them, so no grid-template-columns string is needed for the common case.

<cngx-data-grid-accordion [multi]="true">
  <cngx-dga-header>
    <span cngxDgaCell col="sm">ID</span>
    <span cngxDgaCell col="grow">Name</span>
    <span cngxDgaCell col="md" align="end">Amount</span>
  </cngx-dga-header>
  <cngx-dga-row panelId="1">
    <span cngxDgaCell>1</span>
    <span cngxDgaCell primary>Alpha</span>
    <span cngxDgaCell align="end">120.00</span>
    Detail for row 1
  </cngx-dga-row>
  <cngx-dga-footer>
    <span cngxDgaCell>Total</span>
  </cngx-dga-footer>
</cngx-data-grid-accordion>

https://cngxjs.github.io/cngx/examples/#/ui/data-grid-accordion/sortable-ledger https://cngxjs.github.io/cngx/examples/#/ui/data-grid-accordion/bound-sort-filter https://cngxjs.github.io/cngx/examples/#/ui/data-grid-accordion/master-detail https://cngxjs.github.io/cngx/examples/#/ui/data-grid-accordion/spreadsheet https://cngxjs.github.io/cngx/examples/#/ui/data-grid-accordion/density

Metadata#

Host#

Providers#

CNGX_DATA_GRID_ACCORDION
useExisting CngxDataGridAccordion

Dependencies#

CngxFilterinject()selffilter

The hosted CngxFilter instance, exposed on CNGX_DATA_GRID_ACCORDION as filter. [filterPredicate] forwards to its controlled predicate; consumers read filter.predicate() (or drive addPredicate for facet filtering) and derive the visible rows themselves. State only - the group never hides projected rows.

CngxSortinject()selfsort

The hosted CngxSort instance, exposed on CNGX_DATA_GRID_ACCORDION so cngxDgaSortHeader cells read the shared sort with no [cngxSortRef]. It is a hostDirective, so it lives on this element's injector; { self: true } resolves that instance rather than an ancestor's. The group publishes it as state - the consumer's computed() still derives the ordered rows (Ableitung preserved).

Relationships

Index#

Inputs#

columns#string | undefined
input()

Raw grid-template-columns escape hatch. Leave it unset for the common case: the group derives the shared template from the header cells' col intents (see resolvedColumns). Set it only when a skin needs track syntax the col vocabulary cannot express - ch tracks, subgrid, minmax - such as the spreadsheet skin. When set, it wins over the derived value. It holds content columns only: the disclosure chevron rides a leading gutter outside the grid, so it never consumes a track. Per-instance only - no app-wide config default (unlike [skin]).

filterTerm#string
model()

The simple text filter term, two-way bindable as [(filterTerm)]. A model() because it is a two-way primary value the projected cngxDgaFilter input writes (a plain input() could not be set from the slot). The group publishes it on the context so the consumer's computed() matches it against its own row fields - the group holds no field knowledge and does no matching (Pillar 3).

default ''
headingLevel#
input()

Heading level (2-6) every row's role="heading" wrapper reflects via aria-level. Clamped into the valid ARIA range so a stray 0/9 can never emit an invalid aria-level; the default is clamped explicitly because Angular runs transform only on bound values, not the initial default. Coerced from string via coerceNumberProperty for attribute binding.

default
clampHeadingLevel(3), {    transform: (value: number | string) => clampHeadingLevel(value),  }
input()

Visual skin reflected onto the [data-skin] host attribute. Resolves input ?? CNGX_DATA_GRID_ACCORDION_CONFIG.skin: an unbound [skin] falls back to the app-wide config default (withDataGridSkin); unset on both leaves the base flat grid look. The skin only redirects CSS - structure, cells, ARIA, and keyboard behaviour are identical across skins.

Outputs#

filterTerm#string
model()

The simple text filter term, two-way bindable as [(filterTerm)]. A model() because it is a two-way primary value the projected cngxDgaFilter input writes (a plain input() could not be set from the slot). The group publishes it on the context so the consumer's computed() matches it against its own row fields - the group holds no field knowledge and does no matching (Pillar 3).

HostBindings#

BindingExpression
[attr.data-skin]resolvedSkin() ?? null
[style.--cngx-dga-columns]resolvedColumns()

The eight opt-in visual skins for <cngx-data-grid-accordion>. Pairs with the structural data-grid-accordion.component.css / data-grid-row.component.css in this same entry - those own the flat base grid, the chevron, the region, and the a11y wiring; this file owns only the per-skin paint.

Selected by the [skin] input via the [data-skin] host attribute, mirroring <cngx-accordion-group>. Every skin renders the identical header / row / region structure, cells, ARIA, and keyboard model - only the paint changes. Each value is a CSS @scope (.cngx-data-grid-accordion[data-skin='<name>']) block. Unlayered (this is a component styleUrl, not the Track-B cngx.css), so a [data-skin] rule overrides the flat base by specificity + source order - no @layer battle. Every gradient from the design lab is re-mapped to a solid --cngx-color-primary; the alternate surfaces are derived in oklab from --cngx-color-surface toward --cngx-color-text so they track light / dark without a fixed palette. Container / motion queries stay UNLAYERED with direct selectors, never nested inside @scope (that breaks the token cascade).

  • ledger - a framed table: mono uppercase column head, zebra rows, mono right-aligned amounts, an inset primary-accent detail zone, a sum footer. Below its --cngx-dga-min-width the grid scrolls sideways (host overflow-x) with every column intact rather than dropping one.
  • spreadsheet - an Excel-style sheet: visible cell hairlines, plus a column-letter strip (A / B / C ...) and gutter row numbers BOTH derived from CSS counters - the letters count column position, the numbers count structural rows, so the consumer authors neither. Opening a row fills its gutter cell with the accent colour and the detail zone becomes a warning-tinted note cell. Below its --cngx-dga-min-width the grid scrolls sideways rather than dropping a column.
  • log-stream - a mono log console: timestamp / level / message columns, the row severity doubled as a 3px left edge ([data-severity]), a level badge (projected cngx-tag), an expanded stacktrace pre on a recessed surface, and a flex status footer with a live dot. Below its --cngx-dga-min-width the grid scrolls sideways rather than dropping the timestamp.
  • master-detail - an order/positions view: mono dimmed order number, a weighted customer name, mono right-aligned position + sum cells, and the open row held primary-tinted as the context for its detail. The detail zone is a projected sub-<table> (consumer content the skin only paints) on a recessed surface with a primary inset edge and a quiet sub-head, with a bold rule-free tfoot sum. Below its --cngx-dga-min-width the grid scrolls sideways rather than dropping a column.
  • report - a frameless cost report: no surface frame, a 3px double rule under the column head and over the sum foot, hairline dividers between rows, mono right-aligned budget / actual money, and over-budget actual cells ([data-over]) in the danger colour. Below its --cngx-dga-min-width the grid scrolls sideways rather than dropping a column.
  • density - a framed task list whose row block padding and cell type ride the --cngx-dga-row-py / --cngx-dga-fs hooks, transitioned so a density change animates rather than jumps. The compact / standard / spacious control is a consumer token concern (demo chrome that sets those two tokens), not a component input; the skin only frames the grid and animates the change. Below its --cngx-dga-min-width the grid scrolls sideways rather than dropping a column.