Skip to content

Commit 7ba3c05

Browse files
committed
refactor(multiple): switch the CDK to the inject function
Reworks all of the CDK directives and injectables to use the `inject` function instead of constructor-based injection. All the constructors have a backwards-compatible signature for the apps that may be extending them.
1 parent fead293 commit 7ba3c05

File tree

91 files changed

+873
-933
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+873
-933
lines changed

src/cdk/a11y/a11y-module.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {ObserversModule} from '@angular/cdk/observers';
10-
import {NgModule} from '@angular/core';
10+
import {NgModule, inject} from '@angular/core';
1111
import {CdkMonitorFocus} from './focus-monitor/focus-monitor';
1212
import {CdkTrapFocus} from './focus-trap/focus-trap';
1313
import {HighContrastModeDetector} from './high-contrast-mode/high-contrast-mode-detector';
@@ -18,7 +18,7 @@ import {CdkAriaLive} from './live-announcer/live-announcer';
1818
exports: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],
1919
})
2020
export class A11yModule {
21-
constructor(highContrastModeDetector: HighContrastModeDetector) {
22-
highContrastModeDetector._applyBodyHighContrastModeCssClasses();
21+
constructor() {
22+
inject(HighContrastModeDetector)._applyBodyHighContrastModeCssClasses();
2323
}
2424
}

src/cdk/a11y/aria-describer/aria-describer.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {A11yModule, CDK_DESCRIBEDBY_HOST_ATTRIBUTE} from '../index';
22
import {AriaDescriber} from './aria-describer';
33
import {ComponentFixture, TestBed} from '@angular/core/testing';
4-
import {Component, ElementRef, ViewChild, Provider} from '@angular/core';
4+
import {Component, ElementRef, ViewChild, Provider, inject} from '@angular/core';
55

66
describe('AriaDescriber', () => {
77
let ariaDescriber: AriaDescriber;
@@ -404,6 +404,8 @@ function expectMessage(el: Element, message: string) {
404404
imports: [A11yModule],
405405
})
406406
class TestApp {
407+
ariaDescriber = inject(AriaDescriber);
408+
407409
@ViewChild('element1') _element1: ElementRef<HTMLElement>;
408410
get element1(): Element {
409411
return this._element1.nativeElement;
@@ -423,6 +425,4 @@ class TestApp {
423425
get element4(): Element {
424426
return this._element4.nativeElement;
425427
}
426-
427-
constructor(public ariaDescriber: AriaDescriber) {}
428428
}

src/cdk/a11y/aria-describer/aria-describer.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {DOCUMENT} from '@angular/common';
10-
import {Inject, Injectable, OnDestroy, APP_ID, inject} from '@angular/core';
10+
import {Injectable, OnDestroy, APP_ID, inject} from '@angular/core';
1111
import {Platform} from '@angular/cdk/platform';
1212
import {addAriaReferencedId, getAriaReferenceIds, removeAriaReferencedId} from './aria-reference';
1313

@@ -54,7 +54,8 @@ let nextId = 0;
5454
*/
5555
@Injectable({providedIn: 'root'})
5656
export class AriaDescriber implements OnDestroy {
57-
private _document: Document;
57+
private _platform = inject(Platform);
58+
private _document = inject(DOCUMENT);
5859

5960
/** Map of all registered message elements that have been placed into the document. */
6061
private _messageRegistry = new Map<string | Element, RegisteredMessage>();
@@ -65,15 +66,9 @@ export class AriaDescriber implements OnDestroy {
6566
/** Unique ID for the service. */
6667
private readonly _id = `${nextId++}`;
6768

68-
constructor(
69-
@Inject(DOCUMENT) _document: any,
70-
/**
71-
* @deprecated To be turned into a required parameter.
72-
* @breaking-change 14.0.0
73-
*/
74-
private _platform?: Platform,
75-
) {
76-
this._document = _document;
69+
constructor(...args: unknown[]);
70+
71+
constructor() {
7772
this._id = inject(APP_ID) + '-' + nextId++;
7873
}
7974

src/cdk/a11y/focus-monitor/focus-monitor.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@ import {
1616
Directive,
1717
ElementRef,
1818
EventEmitter,
19-
Inject,
2019
Injectable,
2120
InjectionToken,
2221
NgZone,
2322
OnDestroy,
24-
Optional,
2523
Output,
2624
AfterViewInit,
25+
inject,
2726
} from '@angular/core';
2827
import {Observable, of as observableOf, Subject, Subscription} from 'rxjs';
2928
import {takeUntil} from 'rxjs/operators';
@@ -85,6 +84,10 @@ const captureEventListenerOptions = normalizePassiveListenerOptions({
8584
/** Monitors mouse and keyboard events to determine the cause of focus events. */
8685
@Injectable({providedIn: 'root'})
8786
export class FocusMonitor implements OnDestroy {
87+
private _ngZone = inject(NgZone);
88+
private _platform = inject(Platform);
89+
private readonly _inputModalityDetector = inject(InputModalityDetector);
90+
8891
/** The focus origin that the next focus event is a result of. */
8992
private _origin: FocusOrigin = null;
9093

@@ -138,20 +141,18 @@ export class FocusMonitor implements OnDestroy {
138141
};
139142

140143
/** Used to reference correct document/window */
141-
protected _document?: Document;
144+
protected _document? = inject(DOCUMENT, {optional: true});
142145

143146
/** Subject for stopping our InputModalityDetector subscription. */
144147
private readonly _stopInputModalityDetector = new Subject<void>();
145148

146-
constructor(
147-
private _ngZone: NgZone,
148-
private _platform: Platform,
149-
private readonly _inputModalityDetector: InputModalityDetector,
150-
/** @breaking-change 11.0.0 make document required */
151-
@Optional() @Inject(DOCUMENT) document: any | null,
152-
@Optional() @Inject(FOCUS_MONITOR_DEFAULT_OPTIONS) options: FocusMonitorOptions | null,
153-
) {
154-
this._document = document;
149+
constructor(...args: unknown[]);
150+
151+
constructor() {
152+
const options = inject<FocusMonitorOptions | null>(FOCUS_MONITOR_DEFAULT_OPTIONS, {
153+
optional: true,
154+
});
155+
155156
this._detectionMode = options?.detectionMode || FocusMonitorDetectionMode.IMMEDIATE;
156157
}
157158
/**
@@ -619,15 +620,16 @@ export class FocusMonitor implements OnDestroy {
619620
standalone: true,
620621
})
621622
export class CdkMonitorFocus implements AfterViewInit, OnDestroy {
623+
private _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);
624+
private _focusMonitor = inject(FocusMonitor);
625+
622626
private _monitorSubscription: Subscription;
623627
private _focusOrigin: FocusOrigin = null;
624628

625629
@Output() readonly cdkFocusChange = new EventEmitter<FocusOrigin>();
626630

627-
constructor(
628-
private _elementRef: ElementRef<HTMLElement>,
629-
private _focusMonitor: FocusMonitor,
630-
) {}
631+
constructor(...args: unknown[]);
632+
constructor() {}
631633

632634
get focusOrigin(): FocusOrigin {
633635
return this._focusOrigin;

src/cdk/a11y/focus-trap/configurable-focus-trap-factory.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {DOCUMENT} from '@angular/common';
10-
import {Inject, Injectable, Injector, NgZone, Optional, inject} from '@angular/core';
10+
import {Injectable, Injector, NgZone, inject} from '@angular/core';
1111
import {InteractivityChecker} from '../interactivity-checker/interactivity-checker';
1212
import {ConfigurableFocusTrap} from './configurable-focus-trap';
1313
import {ConfigurableFocusTrapConfig} from './configurable-focus-trap-config';
@@ -18,21 +18,22 @@ import {FocusTrapManager} from './focus-trap-manager';
1818
/** Factory that allows easy instantiation of configurable focus traps. */
1919
@Injectable({providedIn: 'root'})
2020
export class ConfigurableFocusTrapFactory {
21-
private _document: Document;
21+
private _checker = inject(InteractivityChecker);
22+
private _ngZone = inject(NgZone);
23+
private _focusTrapManager = inject(FocusTrapManager);
24+
25+
private _document = inject(DOCUMENT);
2226
private _inertStrategy: FocusTrapInertStrategy;
2327

2428
private readonly _injector = inject(Injector);
2529

26-
constructor(
27-
private _checker: InteractivityChecker,
28-
private _ngZone: NgZone,
29-
private _focusTrapManager: FocusTrapManager,
30-
@Inject(DOCUMENT) _document: any,
31-
@Optional() @Inject(FOCUS_TRAP_INERT_STRATEGY) _inertStrategy?: FocusTrapInertStrategy,
32-
) {
33-
this._document = _document;
30+
constructor(...args: unknown[]);
31+
32+
constructor() {
33+
const inertStrategy = inject(FOCUS_TRAP_INERT_STRATEGY, {optional: true});
34+
3435
// TODO split up the strategies into different modules, similar to DateAdapter.
35-
this._inertStrategy = _inertStrategy || new EventListenerFocusTrapInertStrategy();
36+
this._inertStrategy = inertStrategy || new EventListenerFocusTrapInertStrategy();
3637
}
3738

3839
/**

src/cdk/a11y/focus-trap/configurable-focus-trap.spec.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import {AfterViewInit, Component, ElementRef, Type, ViewChild, Provider} from '@angular/core';
1+
import {
2+
AfterViewInit,
3+
Component,
4+
ElementRef,
5+
Type,
6+
ViewChild,
7+
Provider,
8+
inject,
9+
} from '@angular/core';
210
import {ComponentFixture, TestBed} from '@angular/core/testing';
311
import {
412
A11yModule,
@@ -110,12 +118,12 @@ function createComponent<T>(
110118
standalone: true,
111119
})
112120
class SimpleFocusTrap implements AfterViewInit {
121+
private _focusTrapFactory = inject(ConfigurableFocusTrapFactory);
122+
113123
@ViewChild('focusTrapElement') focusTrapElement!: ElementRef;
114124

115125
focusTrap: ConfigurableFocusTrap;
116126

117-
constructor(private _focusTrapFactory: ConfigurableFocusTrapFactory) {}
118-
119127
ngAfterViewInit() {
120128
this.focusTrap = this._focusTrapFactory.create(this.focusTrapElement.nativeElement);
121129
}

src/cdk/a11y/focus-trap/event-listener-inert-strategy.spec.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import {AfterViewInit, Component, ElementRef, Provider, Type, ViewChild} from '@angular/core';
1+
import {
2+
AfterViewInit,
3+
Component,
4+
ElementRef,
5+
Provider,
6+
Type,
7+
ViewChild,
8+
inject,
9+
} from '@angular/core';
210
import {ComponentFixture, TestBed, fakeAsync, flush} from '@angular/core/testing';
311
import {patchElementFocus} from '../../testing/private';
412
import {
@@ -80,6 +88,8 @@ function createComponent<T>(
8088
standalone: true,
8189
})
8290
class SimpleFocusTrap implements AfterViewInit {
91+
private _focusTrapFactory = inject(ConfigurableFocusTrapFactory);
92+
8393
@ViewChild('focusTrapElement') focusTrapElement!: ElementRef<HTMLElement>;
8494
@ViewChild('outsideFocusable') outsideFocusableElement!: ElementRef<HTMLElement>;
8595
@ViewChild('firstFocusable') firstFocusableElement!: ElementRef<HTMLElement>;
@@ -91,8 +101,6 @@ class SimpleFocusTrap implements AfterViewInit {
91101
// the `document.activeElement`, we need to keep track of it here.
92102
activeElement: Element | null;
93103

94-
constructor(private _focusTrapFactory: ConfigurableFocusTrapFactory) {}
95-
96104
ngAfterViewInit() {
97105
// Ensure consistent focus timing across browsers.
98106
[

src/cdk/a11y/focus-trap/focus-trap.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ViewChild,
77
ViewContainerRef,
88
ViewEncapsulation,
9+
inject as inject_1,
910
} from '@angular/core';
1011
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
1112
import {By} from '@angular/platform-browser';
@@ -481,8 +482,8 @@ class FocusTrapWithoutFocusableElements {
481482
imports: [A11yModule, PortalModule],
482483
})
483484
class FocusTrapInsidePortal {
485+
viewContainerRef = inject_1(ViewContainerRef);
486+
484487
@ViewChild('template') template: TemplateRef<any>;
485488
@ViewChild(CdkPortalOutlet) portalOutlet: CdkPortalOutlet;
486-
487-
constructor(public viewContainerRef: ViewContainerRef) {}
488489
}

src/cdk/a11y/focus-trap/focus-trap.ts

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
Directive,
1414
DoCheck,
1515
ElementRef,
16-
Inject,
1716
Injectable,
1817
Injector,
1918
Input,
@@ -372,16 +371,14 @@ export class FocusTrap {
372371
*/
373372
@Injectable({providedIn: 'root'})
374373
export class FocusTrapFactory {
375-
private _document: Document;
374+
private _checker = inject(InteractivityChecker);
375+
private _ngZone = inject(NgZone);
376+
377+
private _document = inject(DOCUMENT);
376378
private _injector = inject(Injector);
377379

378-
constructor(
379-
private _checker: InteractivityChecker,
380-
private _ngZone: NgZone,
381-
@Inject(DOCUMENT) _document: any,
382-
) {
383-
this._document = _document;
384-
}
380+
constructor(...args: unknown[]);
381+
constructor() {}
385382

386383
/**
387384
* Creates a focus-trapped region around the given element.
@@ -409,6 +406,9 @@ export class FocusTrapFactory {
409406
standalone: true,
410407
})
411408
export class CdkTrapFocus implements OnDestroy, AfterContentInit, OnChanges, DoCheck {
409+
private _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);
410+
private _focusTrapFactory = inject(FocusTrapFactory);
411+
412412
/** Underlying FocusTrap instance. */
413413
focusTrap: FocusTrap;
414414

@@ -432,15 +432,9 @@ export class CdkTrapFocus implements OnDestroy, AfterContentInit, OnChanges, DoC
432432
*/
433433
@Input({alias: 'cdkTrapFocusAutoCapture', transform: booleanAttribute}) autoCapture: boolean;
434434

435-
constructor(
436-
private _elementRef: ElementRef<HTMLElement>,
437-
private _focusTrapFactory: FocusTrapFactory,
438-
/**
439-
* @deprecated No longer being used. To be removed.
440-
* @breaking-change 13.0.0
441-
*/
442-
@Inject(DOCUMENT) _document: any,
443-
) {
435+
constructor(...args: unknown[]);
436+
437+
constructor() {
444438
const platform = inject(Platform);
445439

446440
if (platform.isBrowser) {

src/cdk/a11y/high-contrast-mode/high-contrast-mode-detector.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {inject, Inject, Injectable, OnDestroy} from '@angular/core';
9+
import {inject, Injectable, OnDestroy} from '@angular/core';
1010
import {BreakpointObserver} from '@angular/cdk/layout';
1111
import {Platform} from '@angular/cdk/platform';
1212
import {DOCUMENT} from '@angular/common';
@@ -41,20 +41,19 @@ export const HIGH_CONTRAST_MODE_ACTIVE_CSS_CLASS = 'cdk-high-contrast-active';
4141
*/
4242
@Injectable({providedIn: 'root'})
4343
export class HighContrastModeDetector implements OnDestroy {
44+
private _platform = inject(Platform);
45+
4446
/**
4547
* Figuring out the high contrast mode and adding the body classes can cause
4648
* some expensive layouts. This flag is used to ensure that we only do it once.
4749
*/
4850
private _hasCheckedHighContrastMode: boolean;
49-
private _document: Document;
51+
private _document = inject(DOCUMENT);
5052
private _breakpointSubscription: Subscription;
5153

52-
constructor(
53-
private _platform: Platform,
54-
@Inject(DOCUMENT) document: any,
55-
) {
56-
this._document = document;
54+
constructor(...args: unknown[]);
5755

56+
constructor() {
5857
this._breakpointSubscription = inject(BreakpointObserver)
5958
.observe('(forced-colors: active)')
6059
.subscribe(() => {

0 commit comments

Comments
 (0)