Skip to content

Commit 6e261d4

Browse files
committed
fix(list): disableRipple on selection list not affecting list options after init
Along the same lines as #14836. Fixes changes to `disableRipple` not being propagated immediately the list options.
1 parent 4701c7b commit 6e261d4

File tree

5 files changed

+69
-11
lines changed

5 files changed

+69
-11
lines changed

src/dev-app/list/list-demo.html

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ <h2>Selection list</h2>
119119
<mat-selection-list #groceries [ngModel]="selectedOptions"
120120
(ngModelChange)="onSelectedOptionsChange($event)"
121121
(change)="changeEventCount = changeEventCount + 1"
122-
[disabled]="selectionListDisabled">
122+
[disabled]="selectionListDisabled"
123+
[disableRipple]="selectionListRippleDisabled">
123124
<h3 mat-subheader>Groceries</h3>
124125

125126
<mat-list-option value="bananas" checkboxPosition="before">Bananas</mat-list-option>
@@ -128,7 +129,7 @@ <h3 mat-subheader>Groceries</h3>
128129
<mat-list-option value="strawberries">Strawberries</mat-list-option>
129130
</mat-selection-list>
130131

131-
<mat-selection-list>
132+
<mat-selection-list [disableRipple]="selectionListRippleDisabled">
132133
<h3 mat-subheader>Dogs</h3>
133134

134135
<mat-list-option checkboxPosition="before">
@@ -145,8 +146,16 @@ <h3 mat-subheader>Dogs</h3>
145146
<p>Selected: {{selectedOptions | json}}</p>
146147
<p>Change Event Count {{changeEventCount}}</p>
147148
<p>Model Change Event Count {{modelChangeEventCount}}</p>
148-
<mat-checkbox [(ngModel)]="selectionListDisabled">Disable Selection List</mat-checkbox>
149-
149+
<p>
150+
<mat-checkbox [(ngModel)]="selectionListDisabled">
151+
Disable Selection List
152+
</mat-checkbox>
153+
</p>
154+
<p>
155+
<mat-checkbox [(ngModel)]="selectionListRippleDisabled">
156+
Disable Selection List ripples
157+
</mat-checkbox>
158+
</p>
150159
<p>
151160
<button mat-raised-button (click)="groceries.selectAll()">Select all</button>
152161
<button mat-raised-button (click)="groceries.deselectAll()">Deselect all</button>

src/dev-app/list/list-demo.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export class ListDemo {
6060
thirdLine = false;
6161
infoClicked = false;
6262
selectionListDisabled = false;
63+
selectionListRippleDisabled = false;
6364

6465
selectedOptions: string[] = ['apples'];
6566
changeEventCount = 0;

src/lib/list/selection-list.spec.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
dispatchFakeEvent,
55
dispatchEvent,
66
dispatchKeyboardEvent,
7+
dispatchMouseEvent,
78
} from '@angular/cdk/testing';
89
import {
910
Component,
@@ -13,7 +14,7 @@ import {
1314
ViewChildren,
1415
} from '@angular/core';
1516
import {async, ComponentFixture, fakeAsync, TestBed, tick, flush} from '@angular/core/testing';
16-
import {MatRipple} from '@angular/material/core';
17+
import {MatRipple, defaultRippleAnimationConfig} from '@angular/material/core';
1718
import {By} from '@angular/platform-browser';
1819
import {
1920
MatListModule,
@@ -505,6 +506,33 @@ describe('MatSelectionList without forms', () => {
505506
expect(selectionList.nativeElement.getAttribute('aria-multiselectable')).toBe('true');
506507
});
507508

509+
it('should disable list item ripples when the ripples on the list have been disabled',
510+
fakeAsync(() => {
511+
const rippleTarget = fixture.nativeElement
512+
.querySelector('.mat-list-option:not(.mat-list-item-disabled) .mat-list-item-content');
513+
const {enterDuration, exitDuration} = defaultRippleAnimationConfig;
514+
515+
dispatchMouseEvent(rippleTarget, 'mousedown');
516+
dispatchMouseEvent(rippleTarget, 'mouseup');
517+
518+
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length)
519+
.toBe(1, 'Expected ripples to be enabled by default.');
520+
521+
// Wait for the ripples to go away.
522+
tick(enterDuration + exitDuration);
523+
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length)
524+
.toBe(0, 'Expected ripples to go away.');
525+
526+
fixture.componentInstance.listRippleDisabled = true;
527+
fixture.detectChanges();
528+
529+
dispatchMouseEvent(rippleTarget, 'mousedown');
530+
dispatchMouseEvent(rippleTarget, 'mouseup');
531+
532+
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length)
533+
.toBe(0, 'Expected no ripples after list ripples are disabled.');
534+
}));
535+
508536
});
509537

510538
describe('with list option selected', () => {
@@ -1060,7 +1088,10 @@ describe('MatSelectionList with forms', () => {
10601088

10611089

10621090
@Component({template: `
1063-
<mat-selection-list id="selection-list-1" (selectionChange)="onValueChange($event)">
1091+
<mat-selection-list
1092+
id="selection-list-1"
1093+
(selectionChange)="onValueChange($event)"
1094+
[disableRipple]="listRippleDisabled">
10641095
<mat-list-option checkboxPosition="before" disabled="true" value="inbox">
10651096
Inbox (disabled selection-option)
10661097
</mat-list-option>
@@ -1077,6 +1108,7 @@ describe('MatSelectionList with forms', () => {
10771108
</mat-selection-list>`})
10781109
class SelectionListWithListOptions {
10791110
showLastOption: boolean = true;
1111+
listRippleDisabled = false;
10801112

10811113
onValueChange(_change: MatSelectionListChange) {}
10821114
}

src/lib/list/selection-list.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import {
3838
QueryList,
3939
ViewChild,
4040
ViewEncapsulation,
41+
SimpleChanges,
42+
OnChanges,
4143
} from '@angular/core';
4244
import {
4345
CanDisableRipple, CanDisableRippleCtor,
@@ -290,7 +292,7 @@ export class MatListOption extends _MatListOptionMixinBase
290292
changeDetection: ChangeDetectionStrategy.OnPush
291293
})
292294
export class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption,
293-
CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy {
295+
CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy, OnChanges {
294296

295297
/** The FocusKeyManager which handles focus. */
296298
_keyManager: FocusKeyManager<MatListOption>;
@@ -322,9 +324,7 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
322324
// strategy. Therefore the options will not check for any changes if the `MatSelectionList`
323325
// changed its state. Since we know that a change to `disabled` property of the list affects
324326
// the state of the options, we manually mark each option for check.
325-
if (this.options) {
326-
this.options.forEach(option => option._markForCheck());
327-
}
327+
this._markOptionsForCheck();
328328
}
329329
private _disabled: boolean = false;
330330

@@ -378,6 +378,14 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
378378
});
379379
}
380380

381+
ngOnChanges(changes: SimpleChanges) {
382+
const disableRippleChanges = changes.disableRipple;
383+
384+
if (disableRippleChanges && !disableRippleChanges.firstChange) {
385+
this._markOptionsForCheck();
386+
}
387+
}
388+
381389
ngOnDestroy() {
382390
this._modelChanges.unsubscribe();
383391
}
@@ -572,4 +580,11 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
572580
private _getOptionIndex(option: MatListOption): number {
573581
return this.options.toArray().indexOf(option);
574582
}
583+
584+
/** Marks all the options to be checked in the next change detection run. */
585+
private _markOptionsForCheck() {
586+
if (this.options) {
587+
this.options.forEach(option => option._markForCheck());
588+
}
589+
}
575590
}

tools/public_api_guard/lib/list.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export declare class MatListSubheaderCssMatStyler {
7474
export declare class MatNavList extends _MatListMixinBase implements CanDisableRipple {
7575
}
7676

77-
export declare class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption, CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy {
77+
export declare class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption, CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy, OnChanges {
7878
_keyManager: FocusKeyManager<MatListOption>;
7979
_onTouched: () => void;
8080
compareWith: (o1: any, o2: any) => boolean;
@@ -92,6 +92,7 @@ export declare class MatSelectionList extends _MatSelectionListMixinBase impleme
9292
deselectAll(): void;
9393
focus(): void;
9494
ngAfterContentInit(): void;
95+
ngOnChanges(changes: SimpleChanges): void;
9596
ngOnDestroy(): void;
9697
registerOnChange(fn: (value: any) => void): void;
9798
registerOnTouched(fn: () => void): void;

0 commit comments

Comments
 (0)