Skip to content

Commit 55f9618

Browse files
authored
fix(multiple): remove unnecessary base classes (#27632)
* fix(material/autocomplete): remove base classes * fix(material/checkbox): remove base classes * fix(material/dialog): remove base classes * fix(material/form-field): remove base classes * fix(material/menu): remove base classes * fix(material/paginator): remove base classes * fix(material/radio): remove base classes * fix(material/select): remove base classes * fix(material/slide-toggle): remove base classes * fix(material/snack-bar): remove base classes * fix(material/table): remove base classes * fix(material/tabs): remove base classes * fix(material/tooltip): remove base classes * fix(material/core): remove base classes * fix(material/menu): fix harness test * fix(multiple): update API goldens * fix(multiple): update API to match previous accesible members
1 parent 251581a commit 55f9618

Some content is hidden

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

72 files changed

+1871
-3442
lines changed

src/material/autocomplete/autocomplete-origin.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,6 @@
88

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

11-
/** Base class containing all of the functionality for `MatAutocompleteOrigin`. */
12-
@Directive()
13-
export abstract class _MatAutocompleteOriginBase {
14-
constructor(
15-
/** Reference to the element on which the directive is applied. */
16-
public elementRef: ElementRef<HTMLElement>,
17-
) {}
18-
}
19-
2011
/**
2112
* Directive applied to an element to make it usable
2213
* as a connection point for an autocomplete panel.
@@ -25,4 +16,9 @@ export abstract class _MatAutocompleteOriginBase {
2516
selector: '[matAutocompleteOrigin]',
2617
exportAs: 'matAutocompleteOrigin',
2718
})
28-
export class MatAutocompleteOrigin extends _MatAutocompleteOriginBase {}
19+
export class MatAutocompleteOrigin {
20+
constructor(
21+
/** Reference to the element on which the directive is applied. */
22+
public elementRef: ElementRef<HTMLElement>,
23+
) {}
24+
}

src/material/autocomplete/autocomplete-trigger.ts

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,16 @@ import {
4545
MatOptionSelectionChange,
4646
_countGroupLabelsBeforeOption,
4747
_getOptionScrollPosition,
48-
_MatOptionBase,
48+
MatOption,
4949
} from '@angular/material/core';
5050
import {MAT_FORM_FIELD, MatFormField} from '@angular/material/form-field';
5151
import {defer, fromEvent, merge, Observable, of as observableOf, Subject, Subscription} from 'rxjs';
5252
import {delay, filter, map, switchMap, take, tap, startWith} from 'rxjs/operators';
53-
import {_MatAutocompleteOriginBase} from './autocomplete-origin';
53+
import {MatAutocompleteOrigin} from './autocomplete-origin';
5454
import {
5555
MatAutocompleteDefaultOptions,
5656
MAT_AUTOCOMPLETE_DEFAULT_OPTIONS,
57-
_MatAutocompleteBase,
57+
MatAutocomplete,
5858
} from './autocomplete';
5959

6060
/**
@@ -97,8 +97,29 @@ export const MAT_AUTOCOMPLETE_SCROLL_STRATEGY_FACTORY_PROVIDER = {
9797
};
9898

9999
/** Base class with all of the `MatAutocompleteTrigger` functionality. */
100-
@Directive()
101-
export abstract class _MatAutocompleteTriggerBase
100+
@Directive({
101+
selector: `input[matAutocomplete], textarea[matAutocomplete]`,
102+
host: {
103+
'class': 'mat-mdc-autocomplete-trigger',
104+
'[attr.autocomplete]': 'autocompleteAttribute',
105+
'[attr.role]': 'autocompleteDisabled ? null : "combobox"',
106+
'[attr.aria-autocomplete]': 'autocompleteDisabled ? null : "list"',
107+
'[attr.aria-activedescendant]': '(panelOpen && activeOption) ? activeOption.id : null',
108+
'[attr.aria-expanded]': 'autocompleteDisabled ? null : panelOpen.toString()',
109+
'[attr.aria-controls]': '(autocompleteDisabled || !panelOpen) ? null : autocomplete?.id',
110+
'[attr.aria-haspopup]': 'autocompleteDisabled ? null : "listbox"',
111+
// Note: we use `focusin`, as opposed to `focus`, in order to open the panel
112+
// a little earlier. This avoids issues where IE delays the focusing of the input.
113+
'(focusin)': '_handleFocus()',
114+
'(blur)': '_onTouched()',
115+
'(input)': '_handleInput($event)',
116+
'(keydown)': '_handleKeydown($event)',
117+
'(click)': '_handleClick()',
118+
},
119+
exportAs: 'matAutocompleteTrigger',
120+
providers: [MAT_AUTOCOMPLETE_VALUE_ACCESSOR],
121+
})
122+
export class MatAutocompleteTrigger
102123
implements ControlValueAccessor, AfterViewInit, OnChanges, OnDestroy
103124
{
104125
private _overlayRef: OverlayRef | null;
@@ -141,7 +162,7 @@ export abstract class _MatAutocompleteTriggerBase
141162
* Current option that we have auto-selected as the user is navigating,
142163
* but which hasn't been propagated to the model value yet.
143164
*/
144-
private _pendingAutoselectedOption: _MatOptionBase | null;
165+
private _pendingAutoselectedOption: MatOption | null;
145166

146167
/** Stream of keyboard events that can close the panel. */
147168
private readonly _closeKeyEventStream = new Subject<void>();
@@ -165,7 +186,7 @@ export abstract class _MatAutocompleteTriggerBase
165186
_onTouched = () => {};
166187

167188
/** The autocomplete panel to be attached to this trigger. */
168-
@Input('matAutocomplete') autocomplete: _MatAutocompleteBase;
189+
@Input('matAutocomplete') autocomplete: MatAutocomplete;
169190

170191
/**
171192
* Position of the autocomplete panel relative to the trigger element. A position of `auto`
@@ -180,7 +201,7 @@ export abstract class _MatAutocompleteTriggerBase
180201
* Reference relative to which to position the autocomplete panel.
181202
* Defaults to the autocomplete trigger element.
182203
*/
183-
@Input('matAutocompleteConnectedTo') connectedTo: _MatAutocompleteOriginBase;
204+
@Input('matAutocompleteConnectedTo') connectedTo: MatAutocompleteOrigin;
184205

185206
/**
186207
* `autocomplete` attribute to be set on the input element.
@@ -219,7 +240,7 @@ export abstract class _MatAutocompleteTriggerBase
219240
}
220241

221242
/** Class to apply to the panel when it's above the input. */
222-
protected abstract _aboveClass: string;
243+
private _aboveClass = 'mat-mdc-autocomplete-panel-above';
223244

224245
ngAfterViewInit() {
225246
const window = this._getWindow();
@@ -353,7 +374,7 @@ export abstract class _MatAutocompleteTriggerBase
353374
}) as Observable<MatOptionSelectionChange>;
354375

355376
/** The currently active option, coerced to MatOption type. */
356-
get activeOption(): _MatOptionBase | null {
377+
get activeOption(): MatOption | null {
357378
if (this.autocomplete && this.autocomplete._keyManager) {
358379
return this.autocomplete._keyManager.activeItem;
359380
}
@@ -668,7 +689,7 @@ export abstract class _MatAutocompleteTriggerBase
668689
/**
669690
* Clear any previous selected option and emit a selection change event for this option
670691
*/
671-
private _clearPreviousSelectedOption(skip: _MatOptionBase | null, emitEvent?: boolean) {
692+
private _clearPreviousSelectedOption(skip: MatOption | null, emitEvent?: boolean) {
672693
// Null checks are necessary here, because the autocomplete
673694
// or its options may not have been assigned yet.
674695
this.autocomplete?.options?.forEach(option => {
@@ -984,29 +1005,3 @@ export abstract class _MatAutocompleteTriggerBase
9841005
}
9851006
}
9861007
}
987-
988-
@Directive({
989-
selector: `input[matAutocomplete], textarea[matAutocomplete]`,
990-
host: {
991-
'class': 'mat-mdc-autocomplete-trigger',
992-
'[attr.autocomplete]': 'autocompleteAttribute',
993-
'[attr.role]': 'autocompleteDisabled ? null : "combobox"',
994-
'[attr.aria-autocomplete]': 'autocompleteDisabled ? null : "list"',
995-
'[attr.aria-activedescendant]': '(panelOpen && activeOption) ? activeOption.id : null',
996-
'[attr.aria-expanded]': 'autocompleteDisabled ? null : panelOpen.toString()',
997-
'[attr.aria-controls]': '(autocompleteDisabled || !panelOpen) ? null : autocomplete?.id',
998-
'[attr.aria-haspopup]': 'autocompleteDisabled ? null : "listbox"',
999-
// Note: we use `focusin`, as opposed to `focus`, in order to open the panel
1000-
// a little earlier. This avoids issues where IE delays the focusing of the input.
1001-
'(focusin)': '_handleFocus()',
1002-
'(blur)': '_onTouched()',
1003-
'(input)': '_handleInput($event)',
1004-
'(keydown)': '_handleKeydown($event)',
1005-
'(click)': '_handleClick()',
1006-
},
1007-
exportAs: 'matAutocompleteTrigger',
1008-
providers: [MAT_AUTOCOMPLETE_VALUE_ACCESSOR],
1009-
})
1010-
export class MatAutocompleteTrigger extends _MatAutocompleteTriggerBase {
1011-
protected _aboveClass = 'mat-mdc-autocomplete-panel-above';
1012-
}

src/material/autocomplete/autocomplete.ts

Lines changed: 52 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
ChangeDetectorRef,
1313
Component,
1414
ContentChildren,
15-
Directive,
1615
ElementRef,
1716
EventEmitter,
1817
Inject,
@@ -33,8 +32,6 @@ import {
3332
MatOption,
3433
mixinDisableRipple,
3534
CanDisableRipple,
36-
_MatOptionBase,
37-
_MatOptgroupBase,
3835
ThemePalette,
3936
} from '@angular/material/core';
4037
import {ActiveDescendantKeyManager} from '@angular/cdk/a11y';
@@ -53,19 +50,19 @@ let _uniqueAutocompleteIdCounter = 0;
5350
export class MatAutocompleteSelectedEvent {
5451
constructor(
5552
/** Reference to the autocomplete panel that emitted the event. */
56-
public source: _MatAutocompleteBase,
53+
public source: MatAutocomplete,
5754
/** Option that was selected. */
58-
public option: _MatOptionBase,
55+
public option: MatOption,
5956
) {}
6057
}
6158

6259
/** Event object that is emitted when an autocomplete option is activated. */
6360
export interface MatAutocompleteActivatedEvent {
6461
/** Reference to the autocomplete panel that emitted the event. */
65-
source: _MatAutocompleteBase;
62+
source: MatAutocomplete;
6663

6764
/** Option that was selected. */
68-
option: _MatOptionBase | null;
65+
option: MatOption | null;
6966
}
7067

7168
// Boilerplate for applying mixins to MatAutocomplete.
@@ -112,25 +109,39 @@ export function MAT_AUTOCOMPLETE_DEFAULT_OPTIONS_FACTORY(): MatAutocompleteDefau
112109
};
113110
}
114111

115-
/** Base class with all of the `MatAutocomplete` functionality. */
116-
@Directive()
117-
export abstract class _MatAutocompleteBase
112+
/** Autocomplete component. */
113+
@Component({
114+
selector: 'mat-autocomplete',
115+
templateUrl: 'autocomplete.html',
116+
styleUrls: ['autocomplete.css'],
117+
encapsulation: ViewEncapsulation.None,
118+
changeDetection: ChangeDetectionStrategy.OnPush,
119+
exportAs: 'matAutocomplete',
120+
inputs: ['disableRipple'],
121+
host: {
122+
'class': 'mat-mdc-autocomplete',
123+
'ngSkipHydration': '',
124+
},
125+
providers: [{provide: MAT_OPTION_PARENT_COMPONENT, useExisting: MatAutocomplete}],
126+
animations: [panelAnimation],
127+
})
128+
export class MatAutocomplete
118129
extends _MatAutocompleteMixinBase
119130
implements AfterContentInit, CanDisableRipple, OnDestroy
120131
{
121132
private _activeOptionChanges = Subscription.EMPTY;
122133

123134
/** Class to apply to the panel when it's visible. */
124-
protected abstract _visibleClass: string;
135+
private _visibleClass = 'mat-mdc-autocomplete-visible';
125136

126137
/** Class to apply to the panel when it's hidden. */
127-
protected abstract _hiddenClass: string;
138+
private _hiddenClass = 'mat-mdc-autocomplete-hidden';
128139

129140
/** Emits when the panel animation is done. Null if the panel doesn't animate. */
130-
abstract _animationDone: EventEmitter<AnimationEvent> | null;
141+
_animationDone = new EventEmitter<AnimationEvent>();
131142

132143
/** Manages active item in option list based on key events. */
133-
_keyManager: ActiveDescendantKeyManager<_MatOptionBase>;
144+
_keyManager: ActiveDescendantKeyManager<MatOption>;
134145

135146
/** Whether the autocomplete panel should be visible, depending on option length. */
136147
showPanel: boolean = false;
@@ -160,10 +171,10 @@ export abstract class _MatAutocompleteBase
160171
@ViewChild('panel') panel: ElementRef;
161172

162173
/** Reference to all options within the autocomplete. */
163-
abstract options: QueryList<_MatOptionBase>;
174+
@ContentChildren(MatOption, {descendants: true}) options: QueryList<MatOption>;
164175

165176
/** Reference to all option groups within the autocomplete. */
166-
abstract optionGroups: QueryList<_MatOptgroupBase>;
177+
@ContentChildren(MAT_OPTGROUP, {descendants: true}) optionGroups: QueryList<MatOptgroup>;
167178

168179
/** Aria label of the autocomplete. */
169180
@Input('aria-label') ariaLabel: string;
@@ -253,6 +264,27 @@ export abstract class _MatAutocompleteBase
253264
}
254265
_classList: {[key: string]: boolean} = {};
255266

267+
/** Whether checkmark indicator for single-selection options is hidden. */
268+
@Input()
269+
get hideSingleSelectionIndicator(): boolean {
270+
return this._hideSingleSelectionIndicator;
271+
}
272+
set hideSingleSelectionIndicator(value: BooleanInput) {
273+
this._hideSingleSelectionIndicator = coerceBooleanProperty(value);
274+
this._syncParentProperties();
275+
}
276+
private _hideSingleSelectionIndicator: boolean =
277+
this._defaults.hideSingleSelectionIndicator ?? false;
278+
279+
/** Syncs the parent state with the individual options. */
280+
_syncParentProperties(): void {
281+
if (this.options) {
282+
for (const option of this.options) {
283+
option._changeDetectorRef.markForCheck();
284+
}
285+
}
286+
}
287+
256288
/** Unique ID to be used by autocomplete trigger's "aria-owns" property. */
257289
id: string = `mat-autocomplete-${_uniqueAutocompleteIdCounter++}`;
258290

@@ -281,7 +313,7 @@ export abstract class _MatAutocompleteBase
281313
}
282314

283315
ngAfterContentInit() {
284-
this._keyManager = new ActiveDescendantKeyManager<_MatOptionBase>(this.options)
316+
this._keyManager = new ActiveDescendantKeyManager<MatOption>(this.options)
285317
.withWrap()
286318
.skipPredicate(this._skipPredicate);
287319
this._activeOptionChanges = this._keyManager.change.subscribe(index => {
@@ -297,6 +329,7 @@ export abstract class _MatAutocompleteBase
297329
ngOnDestroy() {
298330
this._keyManager?.destroy();
299331
this._activeOptionChanges.unsubscribe();
332+
this._animationDone.complete();
300333
}
301334

302335
/**
@@ -322,7 +355,7 @@ export abstract class _MatAutocompleteBase
322355
}
323356

324357
/** Emits the `select` event. */
325-
_emitSelectEvent(option: _MatOptionBase): void {
358+
_emitSelectEvent(option: MatOption): void {
326359
const event = new MatAutocompleteSelectedEvent(this, option);
327360
this.optionSelected.emit(event);
328361
}
@@ -350,61 +383,6 @@ export abstract class _MatAutocompleteBase
350383
classList['mat-accent'] = this._color === 'accent';
351384
}
352385

353-
protected _skipPredicate(option: _MatOptionBase) {
354-
return option.disabled;
355-
}
356-
}
357-
358-
@Component({
359-
selector: 'mat-autocomplete',
360-
templateUrl: 'autocomplete.html',
361-
styleUrls: ['autocomplete.css'],
362-
encapsulation: ViewEncapsulation.None,
363-
changeDetection: ChangeDetectionStrategy.OnPush,
364-
exportAs: 'matAutocomplete',
365-
inputs: ['disableRipple'],
366-
host: {
367-
'class': 'mat-mdc-autocomplete',
368-
'ngSkipHydration': '',
369-
},
370-
providers: [{provide: MAT_OPTION_PARENT_COMPONENT, useExisting: MatAutocomplete}],
371-
animations: [panelAnimation],
372-
})
373-
export class MatAutocomplete extends _MatAutocompleteBase implements OnDestroy {
374-
/** Reference to all option groups within the autocomplete. */
375-
@ContentChildren(MAT_OPTGROUP, {descendants: true}) optionGroups: QueryList<MatOptgroup>;
376-
/** Reference to all options within the autocomplete. */
377-
@ContentChildren(MatOption, {descendants: true}) options: QueryList<MatOption>;
378-
protected _visibleClass = 'mat-mdc-autocomplete-visible';
379-
protected _hiddenClass = 'mat-mdc-autocomplete-hidden';
380-
override _animationDone = new EventEmitter<AnimationEvent>();
381-
382-
/** Whether checkmark indicator for single-selection options is hidden. */
383-
@Input()
384-
get hideSingleSelectionIndicator(): boolean {
385-
return this._hideSingleSelectionIndicator;
386-
}
387-
set hideSingleSelectionIndicator(value: BooleanInput) {
388-
this._hideSingleSelectionIndicator = coerceBooleanProperty(value);
389-
this._syncParentProperties();
390-
}
391-
private _hideSingleSelectionIndicator: boolean =
392-
this._defaults.hideSingleSelectionIndicator ?? false;
393-
394-
/** Syncs the parent state with the individual options. */
395-
_syncParentProperties(): void {
396-
if (this.options) {
397-
for (const option of this.options) {
398-
option._changeDetectorRef.markForCheck();
399-
}
400-
}
401-
}
402-
403-
override ngOnDestroy(): void {
404-
super.ngOnDestroy();
405-
this._animationDone.complete();
406-
}
407-
408386
// `skipPredicate` determines if key manager should avoid putting a given option in the tab
409387
// order. Allow disabled list items to receive focus via keyboard to align with WAI ARIA
410388
// recommendation.
@@ -419,7 +397,7 @@ export class MatAutocomplete extends _MatAutocompleteBase implements OnDestroy {
419397
//
420398
// The user can focus disabled options using the keyboard, but the user cannot click disabled
421399
// options.
422-
protected override _skipPredicate(_option: _MatOptionBase) {
400+
protected _skipPredicate() {
423401
return false;
424402
}
425403
}

0 commit comments

Comments
 (0)