fix(selection-list): disabling list doesn't disable ripples of options (#11955)

This commit is contained in:
Paul Gschwendtner
2018-06-29 18:37:54 +02:00
committed by Joey Perrott
parent 195665fb17
commit d3212a6bb8
2 changed files with 48 additions and 5 deletions
+20 -1
View File
@@ -13,6 +13,7 @@ import {
ViewChildren,
} from '@angular/core';
import {async, ComponentFixture, fakeAsync, TestBed, tick, flush} from '@angular/core/testing';
import {MatRipple} from '@angular/material/core';
import {By} from '@angular/platform-browser';
import {
MatListModule,
@@ -626,6 +627,23 @@ describe('MatSelectionList without forms', () => {
expect(selectList.selected.length).toBe(0);
});
it('should update state of options if list state has changed', () => {
// To verify that the template of the list options has been re-rendered after the disabled
// property of the selection list has been updated, the ripple directive can be used.
// Inspecting the host classes of the options doesn't work because those update as part
// of the parent template (of the selection-list).
const listOptionRipple = listOption[2].query(By.directive(MatRipple)).injector.get(MatRipple);
expect(listOptionRipple.disabled)
.toBe(true, 'Expected ripples of list option to be disabled');
fixture.componentInstance.disabled = false;
fixture.detectChanges();
expect(listOptionRipple.disabled)
.toBe(false, 'Expected ripples of list option to be enabled');
});
});
describe('with checkbox position after', () => {
@@ -977,7 +995,7 @@ class SelectionListWithCheckboxPositionAfter {
}
@Component({template: `
<mat-selection-list id="selection-list-3" [disabled]=true>
<mat-selection-list id="selection-list-3" [disabled]="disabled">
<mat-list-option checkboxPosition="after">
Inbox (disabled selection-option)
</mat-list-option>
@@ -992,6 +1010,7 @@ class SelectionListWithCheckboxPositionAfter {
</mat-list-option>
</mat-selection-list>`})
class SelectionListWithListDisabled {
disabled: boolean = true;
}
@Component({template: `
+28 -4
View File
@@ -30,11 +30,9 @@ import {
ViewEncapsulation,
} from '@angular/core';
import {
CanDisable,
CanDisableRipple,
MatLine,
MatLineSetter,
mixinDisabled,
mixinDisableRipple,
} from '@angular/material/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
@@ -43,7 +41,7 @@ import {Subscription} from 'rxjs';
/** @docs-private */
export class MatSelectionListBase {}
export const _MatSelectionListMixinBase = mixinDisableRipple(mixinDisabled(MatSelectionListBase));
export const _MatSelectionListMixinBase = mixinDisableRipple(MatSelectionListBase);
/** @docs-private */
export class MatListOptionBase {}
@@ -238,6 +236,15 @@ export class MatListOption extends _MatListOptionMixinBase
this._changeDetector.markForCheck();
return true;
}
/**
* Notifies Angular that the option needs to be checked in the next change detection run. Mainly
* used to trigger an update of the list option if the disabled state of the selection list
* changed.
*/
_markForCheck() {
this._changeDetector.markForCheck();
}
}
@@ -265,7 +272,7 @@ export class MatListOption extends _MatListOptionMixinBase
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption,
CanDisable, CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy {
CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy {
/** The FocusKeyManager which handles focus. */
_keyManager: FocusKeyManager<MatListOption>;
@@ -287,6 +294,22 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
*/
@Input() compareWith: (o1: any, o2: any) => boolean;
/** Whether the selection list is disabled. */
@Input()
get disabled(): boolean { return this._disabled; }
set disabled(value: boolean) {
this._disabled = coerceBooleanProperty(value);
// The `MatSelectionList` and `MatListOption` are using the `OnPush` change detection
// 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());
}
}
private _disabled: boolean = false;
/** The currently selected options. */
selectedOptions: SelectionModel<MatListOption> = new SelectionModel<MatListOption>(true);
@@ -296,6 +319,7 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
/** Used for storing the values that were assigned before the options were initialized. */
private _tempValues: string[]|null;
/** Subscription to sync value changes in the SelectionModel back to the SelectionList. */
private _modelChanges = Subscription.EMPTY;
/** View to model callback that should be called if the list or its options lost focus. */