angular/components · error · Error
Conditional row definitions via the `when` input are not sup
Error message
Conditional row definitions via the `when` input are not supported when virtual scrolling is enabled, at the moment.
What it means
CdkTable (src/cdk/table/table.ts) validates its inputs during change detection. Row definitions using the `when` predicate input cannot be combined with virtual scrolling, because templates are reused/recycled by the virtual scroll viewport and can change arbitrarily based on the `when` condition (see upstream issue #32670). When both are active in ngDevMode builds, the component throws this Error deliberately to prevent incorrect rendering.
Source
Thrown at src/cdk/table/table.ts:1151
this._headerRowDefs = mergeArrayAndSet(
this._getOwnDefs(this._contentHeaderRowDefs),
this._customHeaderRowDefs,
);
this._footerRowDefs = mergeArrayAndSet(
this._getOwnDefs(this._contentFooterRowDefs),
this._customFooterRowDefs,
);
this._rowDefs = mergeArrayAndSet(this._getOwnDefs(this._contentRowDefs), this._customRowDefs);
// After all row definitions are determined, find the row definition to be considered default.
const defaultRowDefs = this._rowDefs.filter(def => !def.when);
if (typeof ngDevMode === 'undefined' || ngDevMode) {
// At the moment of writing, it's tricky to support `when` with virtual scrolling
// because we reuse templates and they can change arbitrarily based on the `when`
// condition. We may be able to support it in the future (see #32670).
if (this._virtualScrollEnabled() && this._rowDefs.some(def => def.when)) {
throw new Error(
'Conditional row definitions via the `when` input are not ' +
'supported when virtual scrolling is enabled, at the moment.',
);
}
if (!this.multiTemplateDataRows && defaultRowDefs.length > 1) {
throw getTableMultipleDefaultRowDefsError();
}
}
this._defaultRowDef = defaultRowDefs[0];
}
/**
* Check if the header, data, or footer rows have changed what columns they want to display or
* whether the sticky states have changed for the header or footer. If there is a diff, then
* re-render that section.
*/
private _renderUpdatedColumns(): boolean {View on GitHub (pinned to 0411926e7d)
Solutions
- Remove the `when` input from all row definitions and instead switch on row data inside a single row template (e.g. ngIf/ngSwitch within the row template or use data-driven classes).
- Disable virtual scrolling for the table if conditional row definitions are essential, and rely on standard CdkTable rendering.
- Restructure data so all rows share one rowDef, differentiating via the renderRows data and template bindings.
- Track upstream issue #32670 for future support of `when` with virtual scrolling.
Example fix
<!-- before --> <ng-container *cdkRowDef="let row; columns: displayedColumns; when: isSpecialRow">...</ng-container> <!-- after --> <ng-container *cdkRowDef="let row; columns: displayedColumns"> <div [class.special]="isSpecialRow(row)">...</div> </ng-container>
Defensive patterns
Strategy: validation
Validate before calling
// Before enabling virtual scroll on a CdkTable, assert no rowDef uses `when`:
const whenRowDefs = document.querySelectorAll('ng-container[when], [cdkRowDef][when]');
if (whenRowDefs.length > 0 && usingVirtualScroll) {
throw new Error('Remove `when` row defs before enabling cdk virtual scrolling');
} Type guard
function supportsVirtualScroll(rowDefs: Array<{ when?: unknown }>): boolean {
return rowDefs.every(d => d.when === undefined);
} Try / catch
try {
this.viewportComponent.renderRows();
} catch (e) {
if (String(e.message).includes('`when` input are not supported when virtual scrolling')) {
console.error('Refactor row defs: replace `when` predicates with in-template conditionals.');
} else throw e;
} Prevention
- Standardize on one rowDef and differentiate rows inside the template when virtual scrolling is on.
- Add a lint/test rule that fails if [cdkRowDef] elements carry a `when` binding in virtual-scroll tables.
- Track issue #32670 before adopting `when` with virtual scroll.
- Keep dev builds (ngDevMode) in CI so this check fires before production.
When it happens
Trigger: Rendering a <table cdk-table> (or cdk-virtual-scroll based table) where cdkRowDef / *cdkRowDef="let row; when: myWhenFn" rows exist while the virtual scroll is enabled (using <cdk-virtual-scroll-viewport> with the table / multiTemplateDataRows disabled paths that enable _virtualScrollEnabled).
Common situations: Adding `when`-based conditional row styling/structure to an already virtual-scrolling table for large datasets; migrating a regular CdkTable into a virtual scroll viewport and keeping existing `when` row defs; following older tutorials predating this restriction.
Related errors
- Error: attempted to measure an item that isn't rendered.
- cdk-virtual-scroll: scrolledIndexChange is currently not sup
- cdk-virtual-scroll: scrollToIndex is currently not supported
- CDK virtual scroll: maxBufferPx must be greater than or equa
- CDK virtual scroll: maxBufferPx must be greater than or equa
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/e4704f27b8a85856.
Report an issue: GitHub.