Skip to content

Commit

Permalink
fix(list): allow for list and list items to be disabled
Browse files Browse the repository at this point in the history
Adds the ability to disable all variants of the list. Currently it's only the selection list that can be disabled.

Fixes angular#17574.
  • Loading branch information
crisbeto committed Jan 3, 2020
1 parent 09dc459 commit b54fccb
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 16 deletions.
6 changes: 5 additions & 1 deletion src/material/list/list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,8 @@ mat-action-list {
font: inherit;
outline: inherit;
-webkit-tap-highlight-color: transparent;

text-align: left;

[dir='rtl'] & {
text-align: right;
}
Expand All @@ -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;
Expand Down
48 changes: 46 additions & 2 deletions src/material/list/list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('MatList', () => {
ListWithOneAnchorItem, ListWithOneItem, ListWithTwoLineItem, ListWithThreeLineItem,
ListWithAvatar, ListWithItemWithCssClass, ListWithDynamicNumberOfLines,
ListWithMultipleItems, ListWithManyLines, NavListWithOneAnchorItem, ActionListWithoutType,
ActionListWithType, ListWithIndirectDescendantLines
ActionListWithType, ListWithIndirectDescendantLines, ListWithDisabledItems,
],
});

Expand Down Expand Up @@ -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[] = [
Expand Down Expand Up @@ -425,3 +457,15 @@ class ListWithMultipleItems extends BaseTestList { }
})
class ListWithIndirectDescendantLines extends BaseTestList {
}


@Component({template: `
<mat-list [disabled]="listDisabled">
<mat-list-item [disabled]="firstItemDisabled">One</mat-list-item>
<mat-list-item>Two</mat-list-item>
<mat-list-item>Three</mat-list-item>
</mat-list>`})
class ListWithDisabledItems {
firstItemDisabled = false;
listDisabled = false;
}
33 changes: 25 additions & 8 deletions src/material/list/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -21,22 +21,26 @@ 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';

// 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 */
Expand All @@ -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<void>();

Expand All @@ -71,6 +75,7 @@ export class MatNavList extends _MatListMixinBase implements CanDisableRipple, O
}

static ngAcceptInputType_disableRipple: BooleanInput;
static ngAcceptInputType_disabled: BooleanInput;
}

@Component({
Expand All @@ -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<void>();

Expand Down Expand Up @@ -120,6 +126,7 @@ export class MatList extends _MatListMixinBase implements CanDisableRipple, OnCh
}

static ngAcceptInputType_disableRipple: BooleanInput;
static ngAcceptInputType_disabled: BooleanInput;
}

/**
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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);
}
Expand All @@ -223,4 +239,5 @@ export class MatListItem extends _MatListItemMixinBase implements AfterContentIn
}

static ngAcceptInputType_disableRipple: BooleanInput;
static ngAcceptInputType_disabled: BooleanInput;
}
14 changes: 9 additions & 5 deletions tools/public_api_guard/material/list.d.ts
Original file line number Diff line number Diff line change
@@ -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<void>;
constructor(_elementRef: ElementRef<HTMLElement>);
_getListType(): 'list' | 'action-list' | null;
ngOnChanges(): void;
ngOnDestroy(): void;
static ngAcceptInputType_disableRipple: BooleanInput;
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatList, "mat-list, mat-action-list", ["matList"], { 'disableRipple': "disableRipple" }, {}, never>;
static ngAcceptInputType_disabled: BooleanInput;
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatList, "mat-list, mat-action-list", ["matList"], { 'disableRipple': "disableRipple", 'disabled': "disabled" }, {}, never>;
static ɵfac: i0.ɵɵFactoryDef<MatList>;
}

Expand All @@ -25,13 +26,15 @@ export declare class MatListItem extends _MatListItemMixinBase implements AfterC
_avatar: MatListAvatarCssMatStyler;
_icon: MatListIconCssMatStyler;
_lines: QueryList<MatLine>;
disabled: boolean;
constructor(_element: ElementRef<HTMLElement>, _changeDetectorRef: ChangeDetectorRef, navList?: MatNavList, list?: MatList);
_getHostElement(): HTMLElement;
_isRippleDisabled(): boolean;
ngAfterContentInit(): void;
ngOnDestroy(): void;
static ngAcceptInputType_disableRipple: BooleanInput;
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatListItem, "mat-list-item, a[mat-list-item], button[mat-list-item]", ["matListItem"], { 'disableRipple': "disableRipple" }, {}, ["_avatar", "_icon", "_lines"]>;
static ngAcceptInputType_disabled: BooleanInput;
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatListItem, "mat-list-item, a[mat-list-item], button[mat-list-item]", ["matListItem"], { 'disableRipple': "disableRipple", 'disabled': "disabled" }, {}, ["_avatar", "_icon", "_lines"]>;
static ɵfac: i0.ɵɵFactoryDef<MatListItem>;
}

Expand Down Expand Up @@ -78,12 +81,13 @@ export declare class MatListSubheaderCssMatStyler {
static ɵfac: i0.ɵɵFactoryDef<MatListSubheaderCssMatStyler>;
}

export declare class MatNavList extends _MatListMixinBase implements CanDisableRipple, OnChanges, OnDestroy {
export declare class MatNavList extends _MatListMixinBase implements CanDisable, CanDisableRipple, OnChanges, OnDestroy {
_stateChanges: Subject<void>;
ngOnChanges(): void;
ngOnDestroy(): void;
static ngAcceptInputType_disableRipple: BooleanInput;
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatNavList, "mat-nav-list", ["matNavList"], { 'disableRipple': "disableRipple" }, {}, never>;
static ngAcceptInputType_disabled: BooleanInput;
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatNavList, "mat-nav-list", ["matNavList"], { 'disableRipple': "disableRipple", 'disabled': "disabled" }, {}, never>;
static ɵfac: i0.ɵɵFactoryDef<MatNavList>;
}

Expand Down

0 comments on commit b54fccb

Please sign in to comment.