mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(list): disableRipple on selection list not affecting list options after init (#14858)
Along the same lines as #14836. Fixes changes to `disableRipple` not being propagated immediately the list options.
This commit is contained in:
committed by
Jeremy Elbourn
parent
e2c9873196
commit
b98eb0307b
@@ -119,7 +119,8 @@
|
||||
<mat-selection-list #groceries [ngModel]="selectedOptions"
|
||||
(ngModelChange)="onSelectedOptionsChange($event)"
|
||||
(change)="changeEventCount = changeEventCount + 1"
|
||||
[disabled]="selectionListDisabled">
|
||||
[disabled]="selectionListDisabled"
|
||||
[disableRipple]="selectionListRippleDisabled">
|
||||
<h3 mat-subheader>Groceries</h3>
|
||||
|
||||
<mat-list-option value="bananas" checkboxPosition="before">Bananas</mat-list-option>
|
||||
@@ -128,7 +129,7 @@
|
||||
<mat-list-option value="strawberries">Strawberries</mat-list-option>
|
||||
</mat-selection-list>
|
||||
|
||||
<mat-selection-list>
|
||||
<mat-selection-list [disableRipple]="selectionListRippleDisabled">
|
||||
<h3 mat-subheader>Dogs</h3>
|
||||
|
||||
<mat-list-option checkboxPosition="before">
|
||||
@@ -145,8 +146,16 @@
|
||||
<p>Selected: {{selectedOptions | json}}</p>
|
||||
<p>Change Event Count {{changeEventCount}}</p>
|
||||
<p>Model Change Event Count {{modelChangeEventCount}}</p>
|
||||
<mat-checkbox [(ngModel)]="selectionListDisabled">Disable Selection List</mat-checkbox>
|
||||
|
||||
<p>
|
||||
<mat-checkbox [(ngModel)]="selectionListDisabled">
|
||||
Disable Selection List
|
||||
</mat-checkbox>
|
||||
</p>
|
||||
<p>
|
||||
<mat-checkbox [(ngModel)]="selectionListRippleDisabled">
|
||||
Disable Selection List ripples
|
||||
</mat-checkbox>
|
||||
</p>
|
||||
<p>
|
||||
<button mat-raised-button (click)="groceries.selectAll()">Select all</button>
|
||||
<button mat-raised-button (click)="groceries.deselectAll()">Deselect all</button>
|
||||
|
||||
@@ -60,6 +60,7 @@ export class ListDemo {
|
||||
thirdLine = false;
|
||||
infoClicked = false;
|
||||
selectionListDisabled = false;
|
||||
selectionListRippleDisabled = false;
|
||||
|
||||
selectedOptions: string[] = ['apples'];
|
||||
changeEventCount = 0;
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
dispatchFakeEvent,
|
||||
dispatchEvent,
|
||||
dispatchKeyboardEvent,
|
||||
dispatchMouseEvent,
|
||||
} from '@angular/cdk/testing';
|
||||
import {
|
||||
Component,
|
||||
@@ -13,7 +14,7 @@ import {
|
||||
ViewChildren,
|
||||
} from '@angular/core';
|
||||
import {async, ComponentFixture, fakeAsync, TestBed, tick, flush} from '@angular/core/testing';
|
||||
import {MatRipple} from '@angular/material/core';
|
||||
import {MatRipple, defaultRippleAnimationConfig} from '@angular/material/core';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {
|
||||
MatListModule,
|
||||
@@ -521,6 +522,33 @@ describe('MatSelectionList without forms', () => {
|
||||
expect(list.options.toArray().every(option => option.selected)).toBe(true);
|
||||
});
|
||||
|
||||
it('should disable list item ripples when the ripples on the list have been disabled',
|
||||
fakeAsync(() => {
|
||||
const rippleTarget = fixture.nativeElement
|
||||
.querySelector('.mat-list-option:not(.mat-list-item-disabled) .mat-list-item-content');
|
||||
const {enterDuration, exitDuration} = defaultRippleAnimationConfig;
|
||||
|
||||
dispatchMouseEvent(rippleTarget, 'mousedown');
|
||||
dispatchMouseEvent(rippleTarget, 'mouseup');
|
||||
|
||||
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length)
|
||||
.toBe(1, 'Expected ripples to be enabled by default.');
|
||||
|
||||
// Wait for the ripples to go away.
|
||||
tick(enterDuration + exitDuration);
|
||||
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length)
|
||||
.toBe(0, 'Expected ripples to go away.');
|
||||
|
||||
fixture.componentInstance.listRippleDisabled = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
dispatchMouseEvent(rippleTarget, 'mousedown');
|
||||
dispatchMouseEvent(rippleTarget, 'mouseup');
|
||||
|
||||
expect(rippleTarget.querySelectorAll('.mat-ripple-element').length)
|
||||
.toBe(0, 'Expected no ripples after list ripples are disabled.');
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('with list option selected', () => {
|
||||
@@ -1091,7 +1119,10 @@ describe('MatSelectionList with forms', () => {
|
||||
|
||||
|
||||
@Component({template: `
|
||||
<mat-selection-list id="selection-list-1" (selectionChange)="onValueChange($event)">
|
||||
<mat-selection-list
|
||||
id="selection-list-1"
|
||||
(selectionChange)="onValueChange($event)"
|
||||
[disableRipple]="listRippleDisabled">
|
||||
<mat-list-option checkboxPosition="before" disabled="true" value="inbox">
|
||||
Inbox (disabled selection-option)
|
||||
</mat-list-option>
|
||||
@@ -1108,6 +1139,7 @@ describe('MatSelectionList with forms', () => {
|
||||
</mat-selection-list>`})
|
||||
class SelectionListWithListOptions {
|
||||
showLastOption: boolean = true;
|
||||
listRippleDisabled = false;
|
||||
|
||||
onValueChange(_change: MatSelectionListChange) {}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ import {
|
||||
QueryList,
|
||||
ViewChild,
|
||||
ViewEncapsulation,
|
||||
SimpleChanges,
|
||||
OnChanges,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
CanDisableRipple, CanDisableRippleCtor,
|
||||
@@ -299,7 +301,7 @@ export class MatListOption extends _MatListOptionMixinBase
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption,
|
||||
CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy {
|
||||
CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy, OnChanges {
|
||||
|
||||
/** The FocusKeyManager which handles focus. */
|
||||
_keyManager: FocusKeyManager<MatListOption>;
|
||||
@@ -331,9 +333,7 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
|
||||
// strategy. Therefore the options will not check for any changes if the `MatSelectionList`
|
||||
// changed its state. Since we know that a change to `disabled` property of the list affects
|
||||
// the state of the options, we manually mark each option for check.
|
||||
if (this.options) {
|
||||
this.options.forEach(option => option._markForCheck());
|
||||
}
|
||||
this._markOptionsForCheck();
|
||||
}
|
||||
private _disabled: boolean = false;
|
||||
|
||||
@@ -387,6 +387,14 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
|
||||
});
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
const disableRippleChanges = changes.disableRipple;
|
||||
|
||||
if (disableRippleChanges && !disableRippleChanges.firstChange) {
|
||||
this._markOptionsForCheck();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this._modelChanges.unsubscribe();
|
||||
}
|
||||
@@ -581,4 +589,11 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
|
||||
private _getOptionIndex(option: MatListOption): number {
|
||||
return this.options.toArray().indexOf(option);
|
||||
}
|
||||
|
||||
/** Marks all the options to be checked in the next change detection run. */
|
||||
private _markOptionsForCheck() {
|
||||
if (this.options) {
|
||||
this.options.forEach(option => option._markForCheck());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+2
-1
@@ -81,7 +81,7 @@ export declare class MatNavList extends _MatListMixinBase implements CanDisableR
|
||||
ngOnDestroy(): void;
|
||||
}
|
||||
|
||||
export declare class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption, CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy {
|
||||
export declare class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption, CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy, OnChanges {
|
||||
_keyManager: FocusKeyManager<MatListOption>;
|
||||
_onTouched: () => void;
|
||||
compareWith: (o1: any, o2: any) => boolean;
|
||||
@@ -99,6 +99,7 @@ export declare class MatSelectionList extends _MatSelectionListMixinBase impleme
|
||||
deselectAll(): void;
|
||||
focus(): void;
|
||||
ngAfterContentInit(): void;
|
||||
ngOnChanges(changes: SimpleChanges): void;
|
||||
ngOnDestroy(): void;
|
||||
registerOnChange(fn: (value: any) => void): void;
|
||||
registerOnTouched(fn: () => void): void;
|
||||
|
||||
Reference in New Issue
Block a user