Skip to content

Commit 8d3da9e

Browse files
authored
feat(multiple): export aria injection tokens to support custom subclasses (#33607)
1 parent b2f3a08 commit 8d3da9e

15 files changed

Lines changed: 90 additions & 0 deletions

File tree

goldens/aria/accordion/index.api.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66

77
import * as _angular_cdk_bidi from '@angular/cdk/bidi';
88
import * as _angular_core from '@angular/core';
9+
import { InjectionToken } from '@angular/core';
910
import { OnDestroy } from '@angular/core';
1011
import { OnInit } from '@angular/core';
1112
import { Signal } from '@angular/core';
1213

14+
// @public
15+
export const ACCORDION_GROUP: InjectionToken<AccordionGroup>;
16+
1317
// @public
1418
export class AccordionContent {
1519
// (undocumented)

goldens/aria/combobox/index.api.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ComboboxPattern } from '@angular/aria/private';
99
import { ComboboxPopupPattern } from '@angular/aria/private';
1010
import { DeferredContentAware } from '@angular/aria/private';
1111
import * as i1 from '@angular/aria/private';
12+
import { InjectionToken } from '@angular/core';
1213
import { OnDestroy } from '@angular/core';
1314
import { OnInit } from '@angular/core';
1415

@@ -36,6 +37,9 @@ export class Combobox extends DeferredContentAware implements OnInit {
3637
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Combobox, never>;
3738
}
3839

40+
// @public
41+
export const COMBOBOX_POPUP: InjectionToken<ComboboxPopup>;
42+
3943
// @public
4044
export class ComboboxPopup implements OnInit, OnDestroy {
4145
readonly activeDescendant: _angular_core.Signal<string | undefined>;

goldens/aria/grid/index.api.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
import * as _angular_cdk_bidi from '@angular/cdk/bidi';
88
import * as _angular_core from '@angular/core';
99
import { ElementRef } from '@angular/core';
10+
import { InjectionToken } from '@angular/core';
1011
import { OnDestroy } from '@angular/core';
1112
import { OnInit } from '@angular/core';
1213
import { Signal } from '@angular/core';
1314

15+
// @public
16+
export const GRID: InjectionToken<Grid>;
17+
1418
// @public
1519
export class Grid implements OnDestroy {
1620
constructor();
@@ -37,6 +41,12 @@ export class Grid implements OnDestroy {
3741
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Grid, never>;
3842
}
3943

44+
// @public
45+
export const GRID_CELL: InjectionToken<GridCell>;
46+
47+
// @public
48+
export const GRID_ROW: InjectionToken<GridRow>;
49+
4050
// @public
4151
export class GridCell implements OnInit, OnDestroy {
4252
constructor();

goldens/aria/listbox/index.api.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66

77
import * as _angular_cdk_bidi from '@angular/cdk/bidi';
88
import * as _angular_core from '@angular/core';
9+
import { InjectionToken } from '@angular/core';
910
import { OnDestroy } from '@angular/core';
1011
import { OnInit } from '@angular/core';
1112
import { Signal } from '@angular/core';
1213

14+
// @public (undocumented)
15+
export const LISTBOX: InjectionToken<Listbox<any>>;
16+
1317
// @public
1418
export class Listbox<V> implements OnDestroy {
1519
constructor();

goldens/aria/menu/index.api.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import * as _angular_cdk_bidi from '@angular/cdk/bidi';
88
import * as _angular_core from '@angular/core';
9+
import { InjectionToken } from '@angular/core';
910
import { OnDestroy } from '@angular/core';
1011
import { OnInit } from '@angular/core';
1112
import { Signal } from '@angular/core';
@@ -37,6 +38,9 @@ export class Menu<V> implements OnDestroy {
3738
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Menu<any>, never>;
3839
}
3940

41+
// @public
42+
export const MENU_COMPONENT: InjectionToken<Menu<any> | MenuBar<any>>;
43+
4044
// @public
4145
export class MenuBar<V> implements OnDestroy {
4246
constructor();

goldens/aria/tabs/index.api.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import * as _angular_cdk_bidi from '@angular/cdk/bidi';
88
import * as _angular_core from '@angular/core';
9+
import { InjectionToken } from '@angular/core';
910
import { OnDestroy } from '@angular/core';
1011
import { OnInit } from '@angular/core';
1112
import { Signal } from '@angular/core';
@@ -32,6 +33,9 @@ export class Tab implements HasElement, OnInit, OnDestroy {
3233
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Tab, never>;
3334
}
3435

36+
// @public
37+
export const TAB_LIST: InjectionToken<TabList>;
38+
3539
// @public
3640
export class TabContent {
3741
// (undocumented)
@@ -87,6 +91,9 @@ export class TabPanel implements OnInit, OnDestroy {
8791
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TabPanel, never>;
8892
}
8993

94+
// @public
95+
export const TABS: InjectionToken<Tabs>;
96+
9097
// @public
9198
export class Tabs implements OnDestroy {
9299
constructor();

goldens/aria/toolbar/index.api.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import * as _angular_cdk_bidi from '@angular/cdk/bidi';
88
import * as _angular_core from '@angular/core';
9+
import { InjectionToken } from '@angular/core';
910
import { OnDestroy } from '@angular/core';
1011
import { OnInit } from '@angular/core';
1112
import { Signal } from '@angular/core';
@@ -31,6 +32,9 @@ export class Toolbar<V> implements OnDestroy {
3132
static ɵfac: _angular_core.ɵɵFactoryDeclaration<Toolbar<any>, never>;
3233
}
3334

35+
// @public
36+
export const TOOLBAR_WIDGET_GROUP: InjectionToken<ToolbarWidgetGroup<unknown>>;
37+
3438
// @public
3539
export class ToolbarWidget<V> implements OnInit, OnDestroy {
3640
readonly active: _angular_core.Signal<boolean>;

src/aria/accordion/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export {AccordionPanel} from './accordion-panel';
1010
export {AccordionGroup} from './accordion-group';
1111
export {AccordionTrigger} from './accordion-trigger';
1212
export {AccordionContent} from './accordion-content';
13+
export {ACCORDION_GROUP} from './accordion-tokens';
1314

1415
// This needs to be re-exported, because it's used by the accordion components.
1516
// See: https://github.com/angular/components/issues/30663.

src/aria/combobox/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
export {Combobox} from './combobox';
1010
export {ComboboxPopup} from './combobox-popup';
1111
export {ComboboxWidget} from './combobox-widget';
12+
export {COMBOBOX_POPUP} from './combobox-tokens';
1213

1314
// This needs to be re-exported, because it's used by the combobox components.
1415
// See: https://github.com/angular/components/issues/30663.

src/aria/grid/grid.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {Grid} from './grid';
55
import {GridRow} from './grid-row';
66
import {GridCell} from './grid-cell';
77
import {GridCellWidget} from './grid-cell-widget';
8+
import {GRID_ROW, GRID_CELL} from './grid-tokens';
89
import {waitForMicrotasks} from '../private/testing/test-helpers';
910

1011
interface ModifierKeys {
@@ -1174,6 +1175,23 @@ describe('Grid directives', () => {
11741175
expect(consoleSpy).toHaveBeenCalledWith('ngGridRow must contain at least one ngGridCell.');
11751176
});
11761177
});
1178+
1179+
describe('subclassing and custom providers', () => {
1180+
it('should support subclassing GridRow and GridCell using exported injection tokens', async () => {
1181+
TestBed.resetTestingModule();
1182+
TestBed.configureTestingModule({
1183+
imports: [SubclassGridTestComponent],
1184+
});
1185+
const subclassFixture = TestBed.createComponent(SubclassGridTestComponent);
1186+
subclassFixture.detectChanges();
1187+
await subclassFixture.whenStable();
1188+
1189+
const cells = subclassFixture.debugElement.queryAll(By.directive(MyCustomCell));
1190+
expect(cells.length).toBe(2);
1191+
expect(cells[0].nativeElement.getAttribute('role')).toBe('gridcell');
1192+
expect(cells[1].nativeElement.getAttribute('role')).toBe('gridcell');
1193+
});
1194+
});
11771195
});
11781196

11791197
@Component({
@@ -1261,3 +1279,31 @@ class GridTestComponent {
12611279
changeDetection: ChangeDetectionStrategy.Eager,
12621280
})
12631281
class GridRowWithoutCells {}
1282+
1283+
@Component({
1284+
selector: 'my-custom-cell',
1285+
template: `<ng-content></ng-content>`,
1286+
providers: [{provide: GRID_CELL, useExisting: MyCustomCell}],
1287+
})
1288+
class MyCustomCell extends GridCell {}
1289+
1290+
@Component({
1291+
selector: 'my-custom-row',
1292+
template: `<ng-content></ng-content>`,
1293+
providers: [{provide: GRID_ROW, useExisting: MyCustomRow}],
1294+
})
1295+
class MyCustomRow extends GridRow {}
1296+
1297+
@Component({
1298+
template: `
1299+
<table ngGrid>
1300+
<my-custom-row>
1301+
<my-custom-cell>Cell 1</my-custom-cell>
1302+
<my-custom-cell>Cell 2</my-custom-cell>
1303+
</my-custom-row>
1304+
</table>
1305+
`,
1306+
imports: [Grid, MyCustomRow, MyCustomCell],
1307+
changeDetection: ChangeDetectionStrategy.Eager,
1308+
})
1309+
class SubclassGridTestComponent {}

0 commit comments

Comments
 (0)