Skip to content

Commit

Permalink
refactor(multiple): switch material to the inject function (#29731)
Browse files Browse the repository at this point in the history
Switches Material from constructor-based DI to the `inject` function.
  • Loading branch information
crisbeto committed Sep 19, 2024
1 parent 886fb6d commit 5897f37
Show file tree
Hide file tree
Showing 144 changed files with 1,425 additions and 2,111 deletions.
3 changes: 1 addition & 2 deletions src/cdk/a11y/aria-describer/aria-describer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,7 @@ export class AriaDescriber implements OnDestroy {
messagesContainer.classList.add(containerClassName);
messagesContainer.classList.add('cdk-visually-hidden');

// @breaking-change 14.0.0 Remove null check for `_platform`.
if (this._platform && !this._platform.isBrowser) {
if (!this._platform.isBrowser) {
messagesContainer.setAttribute('platform', 'server');
}

Expand Down
6 changes: 0 additions & 6 deletions src/cdk/portal/dom-portal-outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,6 @@ export class DomPortalOutlet extends BasePortalOutlet {
* @breaking-change 10.0.0
*/
override attachDomPortal = (portal: DomPortal) => {
// @breaking-change 10.0.0 Remove check and error once the
// `_document` constructor parameter is required.
if (!this._document && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('Cannot attach DOM portal without _document constructor parameter');
}

const element = portal.element;
if (!element.parentNode && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('DOM portal content must be attached to a parent node.');
Expand Down
6 changes: 0 additions & 6 deletions src/cdk/portal/portal-directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,6 @@ export class CdkPortalOutlet extends BasePortalOutlet implements OnInit, OnDestr
* @breaking-change 10.0.0
*/
override attachDomPortal = (portal: DomPortal) => {
// @breaking-change 9.0.0 Remove check and error once the
// `_document` constructor parameter is required.
if (!this._document && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('Cannot attach DOM portal without _document constructor parameter');
}

const element = portal.element;
if (!element.parentNode && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error('DOM portal content must be attached to a parent node.');
Expand Down
7 changes: 5 additions & 2 deletions src/material-date-fns-adapter/adapter/date-fns-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Inject, Injectable, Optional} from '@angular/core';
import {Injectable, inject} from '@angular/core';
import {DateAdapter, MAT_DATE_LOCALE} from '@angular/material/core';
import {
Locale,
Expand Down Expand Up @@ -52,8 +52,11 @@ const DAY_OF_WEEK_FORMATS = {
/** Adds date-fns support to Angular Material. */
@Injectable()
export class DateFnsAdapter extends DateAdapter<Date, Locale> {
constructor(@Optional() @Inject(MAT_DATE_LOCALE) matDateLocale: {}) {
constructor(...args: unknown[]);

constructor() {
super();
const matDateLocale = inject(MAT_DATE_LOCALE, {optional: true});
this.setLocale(matDateLocale as Locale);
}

Expand Down
17 changes: 10 additions & 7 deletions src/material-luxon-adapter/adapter/luxon-date-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Inject, Injectable, Optional, InjectionToken} from '@angular/core';
import {Injectable, InjectionToken, inject} from '@angular/core';
import {DateAdapter, MAT_DATE_LOCALE} from '@angular/material/core';
import {
DateTime as LuxonDateTime,
Expand Down Expand Up @@ -70,13 +70,16 @@ export class LuxonDateAdapter extends DateAdapter<LuxonDateTime> {
private _firstDayOfWeek: number;
private _defaultOutputCalendar: LuxonCalendarSystem;

constructor(
@Optional() @Inject(MAT_DATE_LOCALE) dateLocale: string,
@Optional()
@Inject(MAT_LUXON_DATE_ADAPTER_OPTIONS)
options?: MatLuxonDateAdapterOptions,
) {
constructor(...args: unknown[]);

constructor() {
super();

const dateLocale = inject(MAT_DATE_LOCALE, {optional: true});
const options = inject<MatLuxonDateAdapterOptions>(MAT_LUXON_DATE_ADAPTER_OPTIONS, {
optional: true,
});

this._useUTC = !!options?.useUtc;
this._firstDayOfWeek = options?.firstDayOfWeek || 0;
this._defaultOutputCalendar = options?.defaultOutputCalendar || 'gregory';
Expand Down
16 changes: 9 additions & 7 deletions src/material-moment-adapter/adapter/moment-date-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Inject, Injectable, Optional, InjectionToken} from '@angular/core';
import {Injectable, InjectionToken, inject} from '@angular/core';
import {DateAdapter, MAT_DATE_LOCALE} from '@angular/material/core';
// Depending on whether rollup is used, moment needs to be imported differently.
// Since Moment.js doesn't have a default export, we normally need to import using the `* as`
Expand Down Expand Up @@ -63,6 +63,10 @@ function range<T>(length: number, valueFunction: (index: number) => T): T[] {
/** Adapts Moment.js Dates for use with Angular Material. */
@Injectable()
export class MomentDateAdapter extends DateAdapter<Moment> {
private _options = inject<MatMomentDateAdapterOptions>(MAT_MOMENT_DATE_ADAPTER_OPTIONS, {
optional: true,
});

// Note: all of the methods that accept a `Moment` input parameter immediately call `this.clone`
// on it. This is to ensure that we're working with a `Moment` that has the correct locale setting
// while avoiding mutating the original object passed to us. Just calling `.locale(...)` on the
Expand All @@ -78,13 +82,11 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
narrowDaysOfWeek: string[];
};

constructor(
@Optional() @Inject(MAT_DATE_LOCALE) dateLocale: string,
@Optional()
@Inject(MAT_MOMENT_DATE_ADAPTER_OPTIONS)
private _options?: MatMomentDateAdapterOptions,
) {
constructor(...args: unknown[]);

constructor() {
super();
const dateLocale = inject<string>(MAT_DATE_LOCALE, {optional: true});
this.setLocale(dateLocale || moment.locale());
}

Expand Down
10 changes: 5 additions & 5 deletions src/material/autocomplete/autocomplete-origin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Directive, ElementRef} from '@angular/core';
import {Directive, ElementRef, inject} from '@angular/core';

/**
* Directive applied to an element to make it usable
Expand All @@ -18,8 +18,8 @@ import {Directive, ElementRef} from '@angular/core';
standalone: true,
})
export class MatAutocompleteOrigin {
constructor(
/** Reference to the element on which the directive is applied. */
public elementRef: ElementRef<HTMLElement>,
) {}
elementRef = inject<ElementRef<HTMLElement>>(ElementRef);

constructor(...args: unknown[]);
constructor() {}
}
38 changes: 17 additions & 21 deletions src/material/autocomplete/autocomplete-trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,12 @@ import {
ChangeDetectorRef,
Directive,
ElementRef,
Host,
Inject,
InjectionToken,
Injector,
Input,
NgZone,
OnChanges,
OnDestroy,
Optional,
SimpleChanges,
ViewContainerRef,
afterNextRender,
Expand Down Expand Up @@ -134,10 +131,24 @@ export const MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY_PROVIDER = {
export class MatAutocompleteTrigger
implements ControlValueAccessor, AfterViewInit, OnChanges, OnDestroy
{
private _element = inject<ElementRef<HTMLInputElement>>(ElementRef);
private _overlay = inject(Overlay);
private _viewContainerRef = inject(ViewContainerRef);
private _zone = inject(NgZone);
private _changeDetectorRef = inject(ChangeDetectorRef);
private _dir = inject(Directionality, {optional: true});
private _formField = inject<MatFormField | null>(MAT_FORM_FIELD, {optional: true, host: true});
private _document = inject(DOCUMENT);
private _viewportRuler = inject(ViewportRuler);
private _defaults = inject<MatAutocompleteDefaultOptions | null>(
MAT_AUTOCOMPLETE_DEFAULT_OPTIONS,
{optional: true},
);

private _overlayRef: OverlayRef | null;
private _portal: TemplatePortal;
private _componentDestroyed = false;
private _scrollStrategy: () => ScrollStrategy;
private _scrollStrategy = inject(MAT_AUTOCOMPLETE_SCROLL_STRATEGY);
private _keydownSubscription: Subscription | null;
private _outsideClickSubscription: Subscription | null;

Expand Down Expand Up @@ -238,23 +249,8 @@ export class MatAutocompleteTrigger

private _injector = inject(Injector);

constructor(
private _element: ElementRef<HTMLInputElement>,
private _overlay: Overlay,
private _viewContainerRef: ViewContainerRef,
private _zone: NgZone,
private _changeDetectorRef: ChangeDetectorRef,
@Inject(MAT_AUTOCOMPLETE_SCROLL_STRATEGY) scrollStrategy: any,
@Optional() private _dir: Directionality | null,
@Optional() @Inject(MAT_FORM_FIELD) @Host() private _formField: MatFormField | null,
@Optional() @Inject(DOCUMENT) private _document: any,
private _viewportRuler: ViewportRuler,
@Optional()
@Inject(MAT_AUTOCOMPLETE_DEFAULT_OPTIONS)
private _defaults?: MatAutocompleteDefaultOptions | null,
) {
this._scrollStrategy = scrollStrategy;
}
constructor(...args: unknown[]);
constructor() {}

/** Class to apply to the panel when it's above the input. */
private _aboveClass = 'mat-mdc-autocomplete-panel-above';
Expand Down
23 changes: 13 additions & 10 deletions src/material/autocomplete/autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
ContentChildren,
ElementRef,
EventEmitter,
Inject,
InjectionToken,
Input,
OnDestroy,
Expand All @@ -24,6 +23,7 @@ import {
ViewChild,
ViewEncapsulation,
booleanAttribute,
inject,
} from '@angular/core';
import {AnimationEvent} from '@angular/animations';
import {
Expand Down Expand Up @@ -119,6 +119,10 @@ export function MAT_AUTOCOMPLETE_DEFAULT_OPTIONS_FACTORY(): MatAutocompleteDefau
standalone: true,
})
export class MatAutocomplete implements AfterContentInit, OnDestroy {
private _changeDetectorRef = inject(ChangeDetectorRef);
private _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);
protected _defaults = inject<MatAutocompleteDefaultOptions>(MAT_AUTOCOMPLETE_DEFAULT_OPTIONS);

private _activeOptionChanges = Subscription.EMPTY;

/** Emits when the panel animation is done. Null if the panel doesn't animate. */
Expand Down Expand Up @@ -252,20 +256,19 @@ export class MatAutocomplete implements AfterContentInit, OnDestroy {
*/
readonly inertGroups: boolean;

constructor(
private _changeDetectorRef: ChangeDetectorRef,
private _elementRef: ElementRef<HTMLElement>,
@Inject(MAT_AUTOCOMPLETE_DEFAULT_OPTIONS) protected _defaults: MatAutocompleteDefaultOptions,
platform?: Platform,
) {
constructor(...args: unknown[]);

constructor() {
const platform = inject(Platform);

// TODO(crisbeto): the problem that the `inertGroups` option resolves is only present on
// Safari using VoiceOver. We should occasionally check back to see whether the bug
// wasn't resolved in VoiceOver, and if it has, we can remove this and the `inertGroups`
// option altogether.
this.inertGroups = platform?.SAFARI || false;
this.autoActiveFirstOption = !!_defaults.autoActiveFirstOption;
this.autoSelectActiveOption = !!_defaults.autoSelectActiveOption;
this.requireSelection = !!_defaults.requireSelection;
this.autoActiveFirstOption = !!this._defaults.autoActiveFirstOption;
this.autoSelectActiveOption = !!this._defaults.autoSelectActiveOption;
this.requireSelection = !!this._defaults.requireSelection;
this._hideSingleSelectionIndicator = this._defaults.hideSingleSelectionIndicator ?? false;
}

Expand Down
23 changes: 11 additions & 12 deletions src/material/badge/badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ import {
Directive,
ElementRef,
inject,
Inject,
Input,
NgZone,
OnDestroy,
OnInit,
Optional,
Renderer2,
ViewEncapsulation,
ANIMATION_MODULE_TYPE,
Expand Down Expand Up @@ -78,6 +76,12 @@ export class _MatBadgeStyleLoader {}
standalone: true,
})
export class MatBadge implements OnInit, OnDestroy {
private _ngZone = inject(NgZone);
private _elementRef = inject<ElementRef<HTMLElement>>(ElementRef);
private _ariaDescriber = inject(AriaDescriber);
private _renderer = inject(Renderer2);
private _animationMode = inject(ANIMATION_MODULE_TYPE, {optional: true});

/**
* Theme color of the badge. This API is supported in M2 themes only, it
* has no effect in M3 themes.
Expand Down Expand Up @@ -150,18 +154,13 @@ export class MatBadge implements OnInit, OnDestroy {

private _document = inject(DOCUMENT);

constructor(
private _ngZone: NgZone,
private _elementRef: ElementRef<HTMLElement>,
private _ariaDescriber: AriaDescriber,
private _renderer: Renderer2,
@Optional() @Inject(ANIMATION_MODULE_TYPE) private _animationMode?: string,
) {
const styleLoader = inject(_CdkPrivateStyleLoader);
styleLoader.load(_MatBadgeStyleLoader);
constructor(...args: unknown[]);

constructor() {
inject(_CdkPrivateStyleLoader).load(_MatBadgeStyleLoader);

if (typeof ngDevMode === 'undefined' || ngDevMode) {
const nativeElement = _elementRef.nativeElement;
const nativeElement = this._elementRef.nativeElement;
if (nativeElement.nodeType !== nativeElement.ELEMENT_NODE) {
throw Error('matBadge must be attached to an element node.');
}
Expand Down
37 changes: 8 additions & 29 deletions src/material/bottom-sheet/bottom-sheet-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,15 @@
*/

import {AnimationEvent} from '@angular/animations';
import {CdkDialogContainer, DialogConfig} from '@angular/cdk/dialog';
import {FocusMonitor, FocusTrapFactory, InteractivityChecker} from '@angular/cdk/a11y';
import {CdkDialogContainer} from '@angular/cdk/dialog';
import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout';
import {OverlayRef} from '@angular/cdk/overlay';
import {DOCUMENT} from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
ElementRef,
EventEmitter,
Inject,
NgZone,
OnDestroy,
Optional,
ViewEncapsulation,
inject,
} from '@angular/core';
import {Subscription} from 'rxjs';
import {matBottomSheetAnimations} from './bottom-sheet-animations';
Expand Down Expand Up @@ -67,27 +61,12 @@ export class MatBottomSheetContainer extends CdkDialogContainer implements OnDes
/** Whether the component has been destroyed. */
private _destroyed: boolean;

constructor(
elementRef: ElementRef,
focusTrapFactory: FocusTrapFactory,
@Optional() @Inject(DOCUMENT) document: any,
config: DialogConfig,
checker: InteractivityChecker,
ngZone: NgZone,
overlayRef: OverlayRef,
breakpointObserver: BreakpointObserver,
focusMonitor?: FocusMonitor,
) {
super(
elementRef,
focusTrapFactory,
document,
config,
checker,
ngZone,
overlayRef,
focusMonitor,
);
constructor(...args: unknown[]);

constructor() {
super();

const breakpointObserver = inject(BreakpointObserver);

this._breakpointSubscription = breakpointObserver
.observe([Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge])
Expand Down
Loading

0 comments on commit 5897f37

Please sign in to comment.