Skip to content

Commit 1fe1f69

Browse files
authored
perf(cdk/table): Optimize a11y role logic in CdkCell. (#28336)
1 parent 96c1b85 commit 1fe1f69

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

src/cdk/table/cell.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,8 @@ export class CdkHeaderCell extends BaseCdkCell {
191191
export class CdkFooterCell extends BaseCdkCell {
192192
constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {
193193
super(columnDef, elementRef);
194-
if (columnDef._table?._elementRef.nativeElement.nodeType === 1) {
195-
const tableRole = columnDef._table._elementRef.nativeElement.getAttribute('role');
196-
const role = tableRole === 'grid' || tableRole === 'treegrid' ? 'gridcell' : 'cell';
194+
const role = columnDef._table?._cellRole;
195+
if (role) {
197196
elementRef.nativeElement.setAttribute('role', role);
198197
}
199198
}
@@ -210,9 +209,8 @@ export class CdkFooterCell extends BaseCdkCell {
210209
export class CdkCell extends BaseCdkCell {
211210
constructor(columnDef: CdkColumnDef, elementRef: ElementRef) {
212211
super(columnDef, elementRef);
213-
if (columnDef._table?._elementRef.nativeElement.nodeType === 1) {
214-
const tableRole = columnDef._table._elementRef.nativeElement.getAttribute('role');
215-
const role = tableRole === 'grid' || tableRole === 'treegrid' ? 'gridcell' : 'cell';
212+
const role = columnDef._table?._cellRole;
213+
if (role) {
216214
elementRef.nativeElement.setAttribute('role', role);
217215
}
218216
}

src/cdk/table/table.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,27 @@ describe('CdkTable', () => {
537537
]);
538538
});
539539

540+
it('defaults to table role in native HTML table', () => {
541+
const fixture = createComponent(NativeHtmlTableApp);
542+
const tableElement = fixture.nativeElement.querySelector('table');
543+
fixture.detectChanges();
544+
expect(tableElement.getAttribute('role')).toBe('table');
545+
546+
expect(getHeaderRows(tableElement)[0].getAttribute('role')).toBe('row');
547+
const header = getHeaderRows(tableElement)[0];
548+
getHeaderCells(header).forEach(cell => {
549+
expect(cell.getAttribute('role')).toBe('columnheader');
550+
});
551+
552+
getRows(tableElement).forEach(row => {
553+
expect(row.getAttribute('role')).toBe('row');
554+
getCells(row).forEach(cell => {
555+
// Native role of TD elements is row.
556+
expect(cell.getAttribute('role')).toBe(null);
557+
});
558+
});
559+
});
560+
540561
it('should be able to nest tables', () => {
541562
const thisFixture = createComponent(NestedHtmlTableApp);
542563
thisFixture.detectChanges();

src/cdk/table/table.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,19 @@ export class CdkTable<T> implements AfterContentChecked, CollectionViewer, OnDes
435435
/** Whether the table has rendered out all the outlets for the first time. */
436436
private _hasRendered = false;
437437

438+
/** Aria role to apply to the table's cells based on the table's own role. */
439+
get _cellRole(): string | null {
440+
if (this._cellRoleInternal === undefined) {
441+
// Perform this lazily in case the table's role was updated by a directive after construction.
442+
const role = this._elementRef.nativeElement.getAttribute('role');
443+
const cellRole = role === 'grid' || role === 'treegrid' ? 'gridcell' : 'cell';
444+
this._cellRoleInternal = this._isNativeHtmlTable && cellRole === 'cell' ? null : cellRole;
445+
}
446+
447+
return this._cellRoleInternal;
448+
}
449+
private _cellRoleInternal: string | null | undefined = undefined;
450+
438451
/**
439452
* Tracking function that will be used to check the differences in data changes. Used similarly
440453
* to `ngFor` `trackBy` function. Optimize row operations by identifying a row based on its data

tools/public_api_guard/cdk/table.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ export class CdkTable<T> implements AfterContentChecked, CollectionViewer, OnDes
296296
addFooterRowDef(footerRowDef: CdkFooterRowDef): void;
297297
addHeaderRowDef(headerRowDef: CdkHeaderRowDef): void;
298298
addRowDef(rowDef: CdkRowDef<T>): void;
299+
get _cellRole(): string | null;
299300
// (undocumented)
300301
protected readonly _changeDetectorRef: ChangeDetectorRef;
301302
// (undocumented)

0 commit comments

Comments
 (0)