diff --git a/src/dev-app/mdc-list/mdc-list-demo.html b/src/dev-app/mdc-list/mdc-list-demo.html index 268f0c511118..4090f8c62aa0 100644 --- a/src/dev-app/mdc-list/mdc-list-demo.html +++ b/src/dev-app/mdc-list/mdc-list-demo.html @@ -116,6 +116,68 @@

Action list

Selection list

- TODO: Implement MDC-based selection list. + +
Groceries
+ + Bananas + Oranges + Apples + Strawberries +
+ + +
Dogs
+ + + + Shiba Inu + + + + + Other Shiba Inu + +
+ +

Selected: {{selectedOptions | json}}

+

Change Event Count {{changeEventCount}}

+

Model Change Event Count {{modelChangeEventCount}}

+

+ + Disable Selection List + +

+

+ + Disable Selection List ripples + +

+

+ + +

+
+ +
+

Single Selection list

+ + +
Favorite Grocery
+ + Bananas + Oranges + Apples + Strawberries +
+ +

Selected: {{favoriteOptions | json}}

diff --git a/src/material-experimental/mdc-list/BUILD.bazel b/src/material-experimental/mdc-list/BUILD.bazel index 917252188cf8..2b5c10615889 100644 --- a/src/material-experimental/mdc-list/BUILD.bazel +++ b/src/material-experimental/mdc-list/BUILD.bazel @@ -22,6 +22,7 @@ ng_module( assets = [":list_scss"] + glob(["**/*.html"]), module_name = "@angular/material-experimental/mdc-list", deps = [ + "//src/cdk/collections", "//src/material/divider", "@npm//@angular/core", "@npm//@angular/forms", diff --git a/src/material-experimental/mdc-list/list-base.ts b/src/material-experimental/mdc-list/list-base.ts index 7aec2ac109b6..090043279999 100644 --- a/src/material-experimental/mdc-list/list-base.ts +++ b/src/material-experimental/mdc-list/list-base.ts @@ -46,6 +46,7 @@ export abstract class MatListItemBase implements AfterContentInit, OnDestroy, Ri rippleConfig: RippleConfig = {}; + // TODO(mmalerba): Add @Input for disabling ripple. rippleDisabled: boolean; private _subscriptions = new Subscription(); diff --git a/src/material-experimental/mdc-list/list-option.html b/src/material-experimental/mdc-list/list-option.html index 05ec09f3cd49..ada597f38597 100644 --- a/src/material-experimental/mdc-list/list-option.html +++ b/src/material-experimental/mdc-list/list-option.html @@ -1 +1,25 @@ -TODO: Implement. + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/material-experimental/mdc-list/list.scss b/src/material-experimental/mdc-list/list.scss index e3b20ede5751..8473180a79a9 100644 --- a/src/material-experimental/mdc-list/list.scss +++ b/src/material-experimental/mdc-list/list.scss @@ -108,3 +108,11 @@ right: 0; opacity: 0; } + +// Normally the `.mdc-list-item__meta` class would be applied to the icon or checkbox directly. +// However, we need to group multiple potential `ng-content` blocks inside the meta section, so we +// add them as children instead. These styles ensure that they are properly aligned. +.mat-mdc-list-option .mdc-list-item__meta .mdc-list-item__graphic { + margin-right: 0; + vertical-align: middle; +} diff --git a/src/material-experimental/mdc-list/module.ts b/src/material-experimental/mdc-list/module.ts index cc11d2eb53dc..bf2fda759dc2 100644 --- a/src/material-experimental/mdc-list/module.ts +++ b/src/material-experimental/mdc-list/module.ts @@ -8,7 +8,7 @@ import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; -import {MatLineModule, MatRippleModule} from '@angular/material/core'; +import {MatLineModule, MatPseudoCheckboxModule, MatRippleModule} from '@angular/material/core'; import {MatDividerModule} from '@angular/material/divider'; import {MatActionList} from './action-list'; import { @@ -26,6 +26,7 @@ import {MatListOption, MatSelectionList} from './selection-list'; CommonModule, MatLineModule, MatRippleModule, + MatPseudoCheckboxModule, ], exports: [ MatList, diff --git a/src/material-experimental/mdc-list/selection-list.html b/src/material-experimental/mdc-list/selection-list.html deleted file mode 100644 index 05ec09f3cd49..000000000000 --- a/src/material-experimental/mdc-list/selection-list.html +++ /dev/null @@ -1 +0,0 @@ -TODO: Implement. diff --git a/src/material-experimental/mdc-list/selection-list.ts b/src/material-experimental/mdc-list/selection-list.ts index bbeb71599fd0..c6f464b8ecd7 100644 --- a/src/material-experimental/mdc-list/selection-list.ts +++ b/src/material-experimental/mdc-list/selection-list.ts @@ -6,19 +6,24 @@ * found in the LICENSE file at https://angular.io/license */ +import {BooleanInput} from '@angular/cdk/coercion'; +import {SelectionModel} from '@angular/cdk/collections'; import {Platform} from '@angular/cdk/platform'; import { ChangeDetectionStrategy, Component, ContentChildren, ElementRef, + EventEmitter, forwardRef, + Input, NgZone, + Output, QueryList, ViewEncapsulation } from '@angular/core'; -import {NG_VALUE_ACCESSOR} from '@angular/forms'; -import {MatLine} from '@angular/material/core'; +import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; +import {MatLine, ThemePalette} from '@angular/material/core'; import {MatListBase, MatListItemBase} from './list-base'; const MAT_SELECTION_LIST_VALUE_ACCESSOR: any = { @@ -40,9 +45,10 @@ export class MatSelectionListChange { selector: 'mat-selection-list', exportAs: 'matSelectionList', host: { - 'class': 'mat-mdc-selection-list mat-mdc-list-base' + 'class': 'mat-mdc-selection-list mat-mdc-list-base mdc-list', + 'role': 'listbox', }, - templateUrl: 'selection-list.html', + template: '', styleUrls: ['list.css'], encapsulation: ViewEncapsulation.None, providers: [ @@ -51,23 +57,68 @@ export class MatSelectionListChange { ], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class MatSelectionList extends MatListBase {} +export class MatSelectionList extends MatListBase implements ControlValueAccessor { + // TODO: Implement these inputs. + @Input() disableRipple: boolean; + @Input() tabIndex: number; + @Input() color: ThemePalette; + @Input() compareWith: (o1: any, o2: any) => boolean; + @Input() disabled: boolean; + @Input() multiple: boolean; + + // TODO: Implement these inputs. + @Output() readonly selectionChange = new EventEmitter(); + + @ContentChildren(forwardRef(() => MatListOption), {descendants: true}) options: + QueryList; + + // TODO: Implement these properties. + selectedOptions: SelectionModel; + + // TODO: Implement these methods. + focus(options?: FocusOptions) {} + selectAll() {} + deselectAll() {} + registerOnChange(fn: any) {} + registerOnTouched(fn: any) {} + writeValue(obj: any) {} +} @Component({ selector: 'mat-list-option', exportAs: 'matListOption', host: { - 'class': 'mat-mdc-list-item mat-mdc-list-option', + 'class': 'mat-mdc-list-item mat-mdc-list-option mdc-list-item', + 'role': 'option', + 'tabindex': '-1', }, templateUrl: 'list-option.html', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, }) export class MatListOption extends MatListItemBase { + static ngAcceptInputType_disabled: BooleanInput; + static ngAcceptInputType_selected: BooleanInput; + static ngAcceptInputType_disableRipple: BooleanInput; + @ContentChildren(MatLine, {read: ElementRef, descendants: true}) lines: QueryList>; - constructor(element: ElementRef, ngZone: NgZone, listBase: MatListBase, platform: Platform) { + // TODO: Implement these inputs. + @Input() disableRipple: boolean; + @Input() checkboxPosition: 'before' | 'after' = 'before'; + @Input() color: ThemePalette; + @Input() value: any; + @Input() disabled: boolean; + @Input() selected: boolean; + + constructor(element: ElementRef, ngZone: NgZone, listBase: MatListBase, platform: Platform, + public selectionList: MatSelectionList) { super(element, ngZone, listBase, platform); } + + // TODO: Implement these methods. + getLabel() { return ''; } + focus() {} + toggle() {} } diff --git a/src/material/list/selection-list.ts b/src/material/list/selection-list.ts index 9a42ca215b43..35179047f201 100644 --- a/src/material/list/selection-list.ts +++ b/src/material/list/selection-list.ts @@ -32,6 +32,7 @@ import { forwardRef, Inject, Input, + isDevMode, OnChanges, OnDestroy, OnInit, @@ -40,7 +41,6 @@ import { SimpleChanges, ViewChild, ViewEncapsulation, - isDevMode, } from '@angular/core'; import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; import { @@ -51,19 +51,14 @@ import { setLines, ThemePalette, } from '@angular/material/core'; - import {Subject} from 'rxjs'; import {startWith, takeUntil} from 'rxjs/operators'; - import {MatListAvatarCssMatStyler, MatListIconCssMatStyler} from './list'; - -/** @docs-private */ class MatSelectionListBase {} const _MatSelectionListMixinBase: CanDisableRippleCtor & typeof MatSelectionListBase = mixinDisableRipple(MatSelectionListBase); -/** @docs-private */ class MatListOptionBase {} const _MatListOptionMixinBase: CanDisableRippleCtor & typeof MatListOptionBase = mixinDisableRipple(MatListOptionBase);