Skip to content

Commit 6c36f8f

Browse files
committed
refactor(material-experimental/mdc-list): remove usage of MDC adapter
Reworks our list not to use MDC's adapters.
1 parent d2ec07b commit 6c36f8f

File tree

6 files changed

+181
-400
lines changed

6 files changed

+181
-400
lines changed

src/material-experimental/mdc-list/BUILD.bazel

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ ng_module(
3333
"//src/material/list",
3434
"@npm//@angular/core",
3535
"@npm//@angular/forms",
36-
"@npm//@material/list",
3736
],
3837
)
3938

@@ -89,7 +88,6 @@ ng_test_library(
8988
"//src/material-experimental/mdc-core",
9089
"@npm//@angular/forms",
9190
"@npm//@angular/platform-browser",
92-
"@npm//@material/list",
9391
],
9492
)
9593

src/material-experimental/mdc-list/interactive-list-base.ts

Lines changed: 0 additions & 225 deletions
This file was deleted.

src/material-experimental/mdc-list/list-base.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export abstract class MatListItemBase implements AfterViewInit, OnDestroy, Rippl
125125
return this.disableRipple || !!this.rippleConfig.disabled;
126126
}
127127

128-
protected constructor(
128+
constructor(
129129
public _elementRef: ElementRef<HTMLElement>,
130130
protected _ngZone: NgZone,
131131
private _listBase: MatListBase,
@@ -166,15 +166,6 @@ export abstract class MatListItemBase implements AfterViewInit, OnDestroy, Rippl
166166
}
167167
}
168168

169-
/** Gets the label for the list item. This is used for the typeahead. */
170-
_getItemLabel(): string {
171-
const titleElement = this._titles?.get(0)?._elementRef.nativeElement;
172-
// If there is no explicit title element, the unscoped text content
173-
// is treated as the list item title.
174-
const labelEl = titleElement ?? this._unscopedContent?.nativeElement;
175-
return labelEl ? labelEl.textContent ?? '' : '';
176-
}
177-
178169
/** Whether the list item has icons or avatars. */
179170
_hasIconOrAvatar() {
180171
return !!(this._avatars.length || this._icons.length);

src/material-experimental/mdc-list/list-option.ts

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,24 @@
88

99
import {BooleanInput, coerceBooleanProperty} from '@angular/cdk/coercion';
1010
import {SelectionModel} from '@angular/cdk/collections';
11-
import {Platform} from '@angular/cdk/platform';
1211
import {
1312
ChangeDetectionStrategy,
1413
ChangeDetectorRef,
1514
Component,
1615
ContentChildren,
1716
ElementRef,
1817
EventEmitter,
19-
Inject,
2018
InjectionToken,
2119
Input,
22-
NgZone,
2320
OnDestroy,
2421
OnInit,
25-
Optional,
2622
Output,
2723
QueryList,
2824
ViewChild,
2925
ViewEncapsulation,
26+
inject,
3027
} from '@angular/core';
31-
import {
32-
MAT_RIPPLE_GLOBAL_OPTIONS,
33-
RippleGlobalOptions,
34-
ThemePalette,
35-
} from '@angular/material-experimental/mdc-core';
36-
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
28+
import {ThemePalette} from '@angular/material-experimental/mdc-core';
3729
import {MatListBase, MatListItemBase} from './list-base';
3830
import {LIST_OPTION, ListOption, MatListOptionCheckboxPosition} from './list-option-types';
3931
import {MatListItemLine, MatListItemTitle} from './list-item-sections';
@@ -56,8 +48,9 @@ export interface SelectionList extends MatListBase {
5648
selectedOptions: SelectionModel<MatListOption>;
5749
compareWith: (o1: any, o2: any) => boolean;
5850
_value: string[] | null;
59-
_reportValueChange: () => void;
60-
_onTouched: () => void;
51+
_reportValueChange(): void;
52+
_emitChangeEvent(options: MatListOption[]): void;
53+
_onTouched(): void;
6154
}
6255

6356
@Component({
@@ -83,7 +76,9 @@ export interface SelectionList extends MatListBase {
8376
'[class.mat-accent]': 'color !== "primary" && color !== "warn"',
8477
'[class.mat-warn]': 'color === "warn"',
8578
'[class._mat-animation-noopable]': '_noopAnimations',
79+
'[attr.aria-selected]': 'selected',
8680
'(blur)': '_handleBlur()',
81+
'(click)': '_toggleOnInteraction()',
8782
},
8883
templateUrl: 'list-option.html',
8984
encapsulation: ViewEncapsulation.None,
@@ -97,7 +92,9 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
9792
@ContentChildren(MatListItemLine, {descendants: true}) _lines: QueryList<MatListItemLine>;
9893
@ContentChildren(MatListItemTitle, {descendants: true}) _titles: QueryList<MatListItemTitle>;
9994
@ViewChild('unscopedContent') _unscopedContent: ElementRef<HTMLSpanElement>;
100-
@ViewChild('text') _itemText: ElementRef<HTMLElement>;
95+
96+
private _selectionList = inject(SELECTION_LIST);
97+
private _changeDetectorRef = inject(ChangeDetectorRef);
10198

10299
/**
103100
* Emits when the selected state of the option has changed.
@@ -158,24 +155,6 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
158155
*/
159156
private _inputsInitialized = false;
160157

161-
constructor(
162-
element: ElementRef,
163-
ngZone: NgZone,
164-
platform: Platform,
165-
@Inject(SELECTION_LIST) public _selectionList: SelectionList,
166-
private _changeDetectorRef: ChangeDetectorRef,
167-
@Optional() @Inject(MAT_RIPPLE_GLOBAL_OPTIONS) globalRippleOptions?: RippleGlobalOptions,
168-
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationMode?: string,
169-
) {
170-
super(element, ngZone, _selectionList, platform, globalRippleOptions, animationMode);
171-
172-
// By default, we mark all options as unselected. The MDC list foundation will
173-
// automatically update the attribute based on selection. Note that we need to
174-
// initially set this because MDC does not set the default attributes for list
175-
// items but expects items to be set up properly in the static markup.
176-
element.nativeElement.setAttribute('aria-selected', 'false');
177-
}
178-
179158
ngOnInit() {
180159
const list = this._selectionList;
181160

@@ -221,6 +200,15 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
221200
this._hostElement.focus();
222201
}
223202

203+
/** Gets the text label of the list option. Used for the typeahead functionality in the list. */
204+
getLabel() {
205+
const titleElement = this._titles?.get(0)?._elementRef.nativeElement;
206+
// If there is no explicit title element, the unscoped text content
207+
// is treated as the list item title.
208+
const labelEl = titleElement || this._unscopedContent?.nativeElement;
209+
return labelEl?.textContent || '';
210+
}
211+
224212
/** Whether a checkbox is shown at the given position. */
225213
_hasCheckboxAt(position: MatListOptionCheckboxPosition): boolean {
226214
return this._selectionList.multiple && this._getCheckboxPosition() === position;
@@ -280,4 +268,22 @@ export class MatListOption extends MatListItemBase implements ListOption, OnInit
280268
_markForCheck() {
281269
this._changeDetectorRef.markForCheck();
282270
}
271+
272+
/** Toggles the option's value based on a user interacion. */
273+
_toggleOnInteraction() {
274+
if (!this.disabled) {
275+
if (this._selectionList.multiple) {
276+
this.selected = !this.selected;
277+
this._selectionList._emitChangeEvent([this]);
278+
} else if (!this.selected) {
279+
this.selected = true;
280+
this._selectionList._emitChangeEvent([this]);
281+
}
282+
}
283+
}
284+
285+
/** Sets the tabindex of the list option. */
286+
_setTabindex(value: number) {
287+
this._hostElement.setAttribute('tabindex', value + '');
288+
}
283289
}

0 commit comments

Comments
 (0)