Skip to content

Commit 1c09ad6

Browse files
committed
add adapter for MDCList
1 parent 0e8d6ba commit 1c09ad6

File tree

3 files changed

+60
-9
lines changed

3 files changed

+60
-9
lines changed

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

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@ import {
1111
AfterContentInit,
1212
Directive,
1313
ElementRef,
14+
forwardRef,
1415
HostBinding,
1516
NgZone,
1617
OnDestroy,
17-
QueryList
18+
QueryList,
19+
ViewChildren
1820
} from '@angular/core';
1921
import {RippleConfig, RippleRenderer, RippleTarget, setLines} from '@angular/material/core';
22+
import {MDCListAdapter} from '@material/list';
2023
import {Subscription} from 'rxjs';
2124
import {startWith} from 'rxjs/operators';
2225

@@ -37,6 +40,46 @@ export abstract class MatListBase {
3740
// tslint:disable-next-line:no-host-decorator-in-concrete
3841
@HostBinding('class.mdc-list--non-interactive')
3942
_isNonInteractive: boolean = false;
43+
44+
@ViewChildren(forwardRef(() => MatListItemBase)) _items: QueryList<MatListItemBase>;
45+
46+
protected adapter: MDCListAdapter = {
47+
getListItemCount: () => this._items.length,
48+
listItemAtIndexHasClass:
49+
(index, className) => this._itemAtIndex(index)._element.classList.contains(className),
50+
addClassForElementIndex:
51+
(index, className) => this._itemAtIndex(index)._element.classList.add(className),
52+
removeClassForElementIndex:
53+
(index, className) => this._itemAtIndex(index)._element.classList.remove(className),
54+
getAttributeForElementIndex:
55+
(index, attr) => this._itemAtIndex(index)._element.getAttribute(attr),
56+
setAttributeForElementIndex:
57+
(index, attr, value) => this._itemAtIndex(index)._element.setAttribute(attr, value),
58+
setTabIndexForListItemChildren:
59+
(index, value) => this._itemAtIndex(index)._element.tabIndex = value as unknown as number,
60+
getFocusedElementIndex:
61+
() => this._items.map(i => i._element).findIndex(e => e === this.doc?.activeELement),
62+
isFocusInsideList: () => this.element.nativeElement.contains(this.doc?.activeElement),
63+
isRootFocused: () => this.element.nativeElement === this.doc?.activeElement,
64+
focusItemAtIndex: index => this._itemAtIndex(index)._element.focus(),
65+
66+
// The following methods have a dummy implementation in the base class because they are only
67+
// applicable to certain types of lists
68+
hasCheckboxAtIndex: () => false,
69+
hasRadioAtIndex: () => false,
70+
setCheckedCheckboxOrRadioAtIndex: () => {},
71+
isCheckboxCheckedAtIndex: () => false,
72+
notifyAction: () => {},
73+
74+
// TODO(mmalerba): Determine if we need to implement this.
75+
getPrimaryTextAtIndex: () => '',
76+
};
77+
78+
constructor(protected element: ElementRef<HTMLElement>, protected doc: any) {}
79+
80+
private _itemAtIndex(index: number): MatListItemBase {
81+
return this._items.toArray()[index];
82+
}
4083
}
4184

4285
@Directive()
@@ -49,20 +92,22 @@ export abstract class MatListItemBase implements AfterContentInit, OnDestroy, Ri
4992
// TODO(mmalerba): Add @Input for disabling ripple.
5093
rippleDisabled: boolean;
5194

95+
_element: HTMLElement;
96+
5297
private _subscriptions = new Subscription();
5398

5499
private _rippleRenderer: RippleRenderer;
55100

56-
constructor(protected _element: ElementRef, protected _ngZone: NgZone, listBase: MatListBase,
57-
platform: Platform) {
58-
const el = this._element.nativeElement;
101+
constructor(private _elementRef: ElementRef<HTMLElement>, protected _ngZone: NgZone,
102+
listBase: MatListBase, platform: Platform) {
103+
this._element = this._elementRef.nativeElement;
59104
this.rippleDisabled = listBase._isNonInteractive;
60105
if (!listBase._isNonInteractive) {
61-
el.classList.add('mat-mdc-list-item-interactive');
106+
this._element.classList.add('mat-mdc-list-item-interactive');
62107
}
63108
this._rippleRenderer =
64-
new RippleRenderer(this, this._ngZone, el, platform);
65-
this._rippleRenderer.setupTriggerEvents(el);
109+
new RippleRenderer(this, this._ngZone, this._element, platform);
110+
this._rippleRenderer.setupTriggerEvents(this._element);
66111
}
67112

68113
ngAfterContentInit() {
@@ -77,14 +122,14 @@ export abstract class MatListItemBase implements AfterContentInit, OnDestroy, Ri
77122
this._ngZone.runOutsideAngular(() => {
78123
this._subscriptions.add(this.lines.changes.pipe(startWith(this.lines))
79124
.subscribe((lines: QueryList<ElementRef<Element>>) => {
80-
this._element.nativeElement.classList
125+
this._element.classList
81126
.toggle('mat-mdc-list-item-single-line', lines.length <= 1);
82127
lines.forEach((line: ElementRef<Element>, index: number) => {
83128
toggleClass(line.nativeElement,
84129
'mdc-list-item__primary-text', index === 0 && lines.length > 1);
85130
toggleClass(line.nativeElement, 'mdc-list-item__secondary-text', index !== 0);
86131
});
87-
setLines(lines, this._element, 'mat-mdc');
132+
setLines(lines, this._elementRef, 'mat-mdc');
88133
}));
89134
});
90135
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ export class MatList extends MatListBase {
7979
templateUrl: 'list-item.html',
8080
encapsulation: ViewEncapsulation.None,
8181
changeDetection: ChangeDetectionStrategy.OnPush,
82+
providers: [
83+
{provide: MatListItemBase, useExisting: MatListItem},
84+
]
8285
})
8386
export class MatListItem extends MatListItemBase {
8487
@ContentChildren(MatLine, {read: ElementRef, descendants: true}) lines:

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ export class MatSelectionList extends MatListBase implements ControlValueAccesso
9595
templateUrl: 'list-option.html',
9696
encapsulation: ViewEncapsulation.None,
9797
changeDetection: ChangeDetectionStrategy.OnPush,
98+
providers: [
99+
{provide: MatListItemBase, useExisting: MatListOption},
100+
]
98101
})
99102
export class MatListOption extends MatListItemBase {
100103
static ngAcceptInputType_disabled: BooleanInput;

0 commit comments

Comments
 (0)