diff --git a/src/material/list/list.scss b/src/material/list/list.scss
index b38b5f7d1e9e..fce0ce3f8405 100644
--- a/src/material/list/list.scss
+++ b/src/material/list/list.scss
@@ -278,8 +278,8 @@ mat-action-list {
font: inherit;
outline: inherit;
-webkit-tap-highlight-color: transparent;
-
text-align: left;
+
[dir='rtl'] & {
text-align: right;
}
@@ -300,6 +300,10 @@ mat-action-list {
outline: none;
}
+.mat-list-item-disabled {
+ pointer-events: none;
+}
+
@include cdk-high-contrast {
.mat-selection-list:focus {
outline-style: dotted;
diff --git a/src/material/list/list.spec.ts b/src/material/list/list.spec.ts
index 208bdec247d8..e8ae421da7ca 100644
--- a/src/material/list/list.spec.ts
+++ b/src/material/list/list.spec.ts
@@ -16,7 +16,7 @@ describe('MatList', () => {
ListWithOneAnchorItem, ListWithOneItem, ListWithTwoLineItem, ListWithThreeLineItem,
ListWithAvatar, ListWithItemWithCssClass, ListWithDynamicNumberOfLines,
ListWithMultipleItems, ListWithManyLines, NavListWithOneAnchorItem, ActionListWithoutType,
- ActionListWithType, ListWithIndirectDescendantLines
+ ActionListWithType, ListWithIndirectDescendantLines, ListWithDisabledItems,
],
});
@@ -275,8 +275,40 @@ describe('MatList', () => {
expect(listItems[0].nativeElement.className).toContain('mat-2-line');
expect(listItems[1].nativeElement.className).toContain('mat-2-line');
});
-});
+ it('should be able to disable a single list item', () => {
+ const fixture = TestBed.createComponent(ListWithDisabledItems);
+ const listItems: HTMLElement[] =
+ Array.from(fixture.nativeElement.querySelectorAll('mat-list-item'));
+ fixture.detectChanges();
+
+ expect(listItems.map(item => {
+ return item.classList.contains('mat-list-item-disabled');
+ })).toEqual([false, false, false]);
+
+ fixture.componentInstance.firstItemDisabled = true;
+ fixture.detectChanges();
+
+ expect(listItems.map(item => {
+ return item.classList.contains('mat-list-item-disabled');
+ })).toEqual([true, false, false]);
+ });
+
+ it('should be able to disable the entire list', () => {
+ const fixture = TestBed.createComponent(ListWithDisabledItems);
+ const listItems: HTMLElement[] =
+ Array.from(fixture.nativeElement.querySelectorAll('mat-list-item'));
+ fixture.detectChanges();
+
+ expect(listItems.every(item => item.classList.contains('mat-list-item-disabled'))).toBe(false);
+
+ fixture.componentInstance.listDisabled = true;
+ fixture.detectChanges();
+
+ expect(listItems.every(item => item.classList.contains('mat-list-item-disabled'))).toBe(true);
+ });
+
+});
class BaseTestList {
items: any[] = [
@@ -425,3 +457,15 @@ class ListWithMultipleItems extends BaseTestList { }
})
class ListWithIndirectDescendantLines extends BaseTestList {
}
+
+
+@Component({template: `
+
+ One
+ Two
+ Three
+ `})
+class ListWithDisabledItems {
+ firstItemDisabled = false;
+ listDisabled = false;
+}
diff --git a/src/material/list/list.ts b/src/material/list/list.ts
index 2be160ab501c..f51d41b4d295 100644
--- a/src/material/list/list.ts
+++ b/src/material/list/list.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {BooleanInput} from '@angular/cdk/coercion';
+import {coerceBooleanProperty, BooleanInput} from '@angular/cdk/coercion';
import {
AfterContentInit,
ChangeDetectionStrategy,
@@ -21,13 +21,17 @@ import {
OnChanges,
OnDestroy,
ChangeDetectorRef,
+ Input,
} from '@angular/core';
import {
+ CanDisable,
+ CanDisableCtor,
CanDisableRipple,
CanDisableRippleCtor,
MatLine,
setLines,
mixinDisableRipple,
+ mixinDisabled,
} from '@angular/material/core';
import {Subject} from 'rxjs';
import {takeUntil} from 'rxjs/operators';
@@ -35,8 +39,8 @@ import {takeUntil} from 'rxjs/operators';
// Boilerplate for applying mixins to MatList.
/** @docs-private */
class MatListBase {}
-const _MatListMixinBase: CanDisableRippleCtor & typeof MatListBase =
- mixinDisableRipple(MatListBase);
+const _MatListMixinBase: CanDisableRippleCtor & CanDisableCtor & typeof MatListBase =
+ mixinDisabled(mixinDisableRipple(MatListBase));
// Boilerplate for applying mixins to MatListItem.
/** @docs-private */
@@ -53,12 +57,12 @@ const _MatListItemMixinBase: CanDisableRippleCtor & typeof MatListItemBase =
},
templateUrl: 'list.html',
styleUrls: ['list.css'],
- inputs: ['disableRipple'],
+ inputs: ['disableRipple', 'disabled'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class MatNavList extends _MatListMixinBase implements CanDisableRipple, OnChanges,
- OnDestroy {
+export class MatNavList extends _MatListMixinBase implements CanDisable, CanDisableRipple,
+ OnChanges, OnDestroy {
/** Emits when the state of the list changes. */
_stateChanges = new Subject();
@@ -71,6 +75,7 @@ export class MatNavList extends _MatListMixinBase implements CanDisableRipple, O
}
static ngAcceptInputType_disableRipple: BooleanInput;
+ static ngAcceptInputType_disabled: BooleanInput;
}
@Component({
@@ -81,11 +86,12 @@ export class MatNavList extends _MatListMixinBase implements CanDisableRipple, O
'class': 'mat-list mat-list-base'
},
styleUrls: ['list.css'],
- inputs: ['disableRipple'],
+ inputs: ['disableRipple', 'disabled'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class MatList extends _MatListMixinBase implements CanDisableRipple, OnChanges, OnDestroy {
+export class MatList extends _MatListMixinBase implements CanDisable, CanDisableRipple, OnChanges,
+ OnDestroy {
/** Emits when the state of the list changes. */
_stateChanges = new Subject();
@@ -120,6 +126,7 @@ export class MatList extends _MatListMixinBase implements CanDisableRipple, OnCh
}
static ngAcceptInputType_disableRipple: BooleanInput;
+ static ngAcceptInputType_disabled: BooleanInput;
}
/**
@@ -158,6 +165,7 @@ export class MatListSubheaderCssMatStyler {}
exportAs: 'matListItem',
host: {
'class': 'mat-list-item',
+ '[class.mat-list-item-disabled]': 'disabled',
// @breaking-change 8.0.0 Remove `mat-list-item-avatar` in favor of `mat-list-item-with-avatar`.
'[class.mat-list-item-avatar]': '_avatar || _icon',
'[class.mat-list-item-with-avatar]': '_avatar || _icon',
@@ -202,6 +210,14 @@ export class MatListItem extends _MatListItemMixinBase implements AfterContentIn
}
}
+ /** Whether the option is disabled. */
+ @Input()
+ get disabled() { return this._disabled || !!(this._list && this._list.disabled); }
+ set disabled(value: boolean) {
+ this._disabled = coerceBooleanProperty(value);
+ }
+ private _disabled = false;
+
ngAfterContentInit() {
setLines(this._lines, this._element);
}
@@ -223,4 +239,5 @@ export class MatListItem extends _MatListItemMixinBase implements AfterContentIn
}
static ngAcceptInputType_disableRipple: BooleanInput;
+ static ngAcceptInputType_disabled: BooleanInput;
}
diff --git a/tools/public_api_guard/material/list.d.ts b/tools/public_api_guard/material/list.d.ts
index 2ad5258a63fe..519bf239fd23 100644
--- a/tools/public_api_guard/material/list.d.ts
+++ b/tools/public_api_guard/material/list.d.ts
@@ -1,13 +1,14 @@
export declare const MAT_SELECTION_LIST_VALUE_ACCESSOR: any;
-export declare class MatList extends _MatListMixinBase implements CanDisableRipple, OnChanges, OnDestroy {
+export declare class MatList extends _MatListMixinBase implements CanDisable, CanDisableRipple, OnChanges, OnDestroy {
_stateChanges: Subject;
constructor(_elementRef: ElementRef);
_getListType(): 'list' | 'action-list' | null;
ngOnChanges(): void;
ngOnDestroy(): void;
static ngAcceptInputType_disableRipple: BooleanInput;
- static ɵcmp: i0.ɵɵComponentDefWithMeta;
+ static ngAcceptInputType_disabled: BooleanInput;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
static ɵfac: i0.ɵɵFactoryDef;
}
@@ -25,13 +26,16 @@ export declare class MatListItem extends _MatListItemMixinBase implements AfterC
_avatar: MatListAvatarCssMatStyler;
_icon: MatListIconCssMatStyler;
_lines: QueryList;
+ get disabled(): boolean;
+ set disabled(value: boolean);
constructor(_element: ElementRef, _changeDetectorRef: ChangeDetectorRef, navList?: MatNavList, list?: MatList);
_getHostElement(): HTMLElement;
_isRippleDisabled(): boolean;
ngAfterContentInit(): void;
ngOnDestroy(): void;
static ngAcceptInputType_disableRipple: BooleanInput;
- static ɵcmp: i0.ɵɵComponentDefWithMeta;
+ static ngAcceptInputType_disabled: BooleanInput;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
static ɵfac: i0.ɵɵFactoryDef;
}
@@ -82,12 +86,13 @@ export declare class MatListSubheaderCssMatStyler {
static ɵfac: i0.ɵɵFactoryDef;
}
-export declare class MatNavList extends _MatListMixinBase implements CanDisableRipple, OnChanges, OnDestroy {
+export declare class MatNavList extends _MatListMixinBase implements CanDisable, CanDisableRipple, OnChanges, OnDestroy {
_stateChanges: Subject;
ngOnChanges(): void;
ngOnDestroy(): void;
static ngAcceptInputType_disableRipple: BooleanInput;
- static ɵcmp: i0.ɵɵComponentDefWithMeta;
+ static ngAcceptInputType_disabled: BooleanInput;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
static ɵfac: i0.ɵɵFactoryDef;
}