Active Foundation

Search documentation

Search all pages, headings and text, in the current package or topic or in all documentation.

Server grouping

Grouping on the server: one group path at a time, what the server owns and what the grid owns.

@workspace/active-grid 11.0.0Status unknowncontent differs from the recorded release 11.0.0baseline ce081dc3

The package's own guide

This guide is the package's docs/guides/server-grouping.md, included unchanged from the package as it is in Foundation. Links to the package's internal design documents keep their text.

Server grouping fetches one group path at a time. The server owns group membership, authorization, query execution and aggregate values. The grid owns expansion controls, loading state, cached children and synthetic display rows. Client grouping instead runs in the kernel over loaded source records.

Enabling#

Use the resource-backed fetch adapter and server-declared capabilities from Resource-backed server mode. Grouping must be enabled both for the grid and for its server mode. This fragment assumes the host supplies fetchOrders, capabilities, columns and the reader's locale:

TSX
<ActiveGrid  gridId="orders-by-region"  locale={locale}  mode="server"  fetchFn={fetchOrders}  serverCapabilities={capabilities}  columns={columns}  enableGrouping  enableServerGrouping  serverGroupBy={[{field: 'region', sort: 'asc'}, {field: 'category'}]}/>

serverGroupBy is an ordered GroupByColumn[], not an array of strings. The server capability map determines which fields may be grouped and aggregated. Do not configure the removed serverGroupAggregations component prop.

How requests look#

The grouping hook calls fetchFn with the ordinary ServerFetchParams (pageIndex, fetchSize, sorting, filters, globalFilter, signal) plus:

  • groupBy: ordered {field, sort?} declarations;

  • groupKeys: the path being fetched; [] means top level, ['Europe'] means children of that region.

There is no expandedGroups request field. Expansion state stays in the outer hook; each fetch asks for one path. The optional historical groupAggregations wire field remains declared but the grid does not populate it. Resource aggregation policy belongs to the server resource declaration.

fetchSize is a fetch-block size, distinct from the visible page size. A resource group listing returns its complete permitted group listing or refuses it according to the server's grouping limits; it is not a silently truncated leaf page. Leaf requests use paging. See Server mode.

Grouped response#

A fetch resolves to PagedResponse<TData>, not an action envelope containing rows. The resource adapter unwraps its action response. For grouped results, isGrouped: true and groups: GroupInfo[] describe the groups. For example:

typescript
import type {GroupInfo} from '@workspace/active-grid';
const groups: GroupInfo[] = [  {    key: 'Europe',    count: 42,    aggregations: {amount: 1250},    hasSubGroups: true,  },];

PagedResponse.data remains the response data field; totalCount is the count for the requested level. For a leaf result, return its records in data without grouped metadata. The server revalidates the grouping path, filters and sorting and applies its own authorization at every level.

Synthetic display rows#

The grouping hook constructs a ServerGroupRow from each GroupInfo: __isServerGroup, __groupField, __groupValue, __groupCount, optional __groupAggregations / __hasSubGroups, __groupKeys and __depth. These markers describe the outer server-grouping representation. They are separate from the kernel's client-generated GeneratedRow union member.

Each synthetic row is a row of the grid for assistive technology too: it carries the same logical aria-rowindex as the rows around it, so group rows, loaded records and load-more rows form one unbroken sequence, also in the mounted window of a virtualized body.

Use isServerGroupRow(value) to narrow a server marker and isServerLoadMoreRow(value) for a load-more marker. The outer owner supplies synthetic IDs before the domain row-ID callback; that callback remains about real records. Do not pretend a synthetic group is an ordinary domain record.

Load-more rows#

When loaded children do not reach the level's total, the hook creates a ServerLoadMoreRow with __isServerLoadMore, __groupKeys, __loadedCount, __totalCount and __depth. Activating it fetches the next block for that path and appends the accepted children. The server returns records and counts; it does not need to manufacture this UI marker. A load-more row stands under a leaf group only.

The row is a row of the grid's keyboard navigation. The arrow keys reach it, and Enter or Space on any of its cells activates it; a click does the same, through the same action. It is named by its label ("10 of 42 loaded (load more)"), its cells carry aria-keyshortcuts="Enter Space", and while the block is loading the row is aria-busy and a second activation asks for nothing. When the block lands, the active cell keeps its display position, which now holds the first new row; see Keyboard.

Rendering aggregations#

Group metadata's aggregations map becomes __groupAggregations on the synthetic display row. Keys correspond to column IDs. The server-declared aggregate capability and column presentation semantics determine the display. A source-record formatter must not be called with a made-up group record; see the callback contract in Columns. Client grouping separately requires a declared aggregationFn (DC-3).

State persistence#

Server-group expansion is local React state in the grouping hook. It is not persisted to localStorage or the URL. This differs from the kernel's client expanded slice. The URL owns only page, pageSize, sort, filters and search; see URL state.

Performance#

Loaded group children can be reused while their cache entry remains valid. Sorting, filtering, global search and grouping changes invalidate the grouping dataset and collapse its local expansion state. Explicit refresh and cache eviction also prevent a blanket promise of zero refetches. Load-more keeps leaf fetches bounded; the grid does not load the entire leaf dataset to group it.

Reference#

  • Current architecture: kernel and outer ownership.

  • Server contract: client declarations and hydration.

  • Resource-backed server mode: supported server adapter.

  • E2E harness: current grouping fixture navigation.

This page as Markdown