Skip to content

Commit

Permalink
fix(selection-list): disabling list doesn't disable ripples of options
Browse files Browse the repository at this point in the history
* Fixes that dynamically changing the `[disabled]` binding does not update the state of the list options (e.g. ripple disabled state; checkbox disabled styling)

Fixes #9952
  • Loading branch information
devversion committed Jun 27, 2018
1 parent d96adbe commit b3977d0
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
21 changes: 20 additions & 1 deletion src/lib/list/selection-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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>
Expand All @@ -992,6 +1010,7 @@ class SelectionListWithCheckboxPositionAfter {
</mat-list-option>
</mat-selection-list>`})
class SelectionListWithListDisabled {
disabled: boolean = true;
}

@Component({template: `
Expand Down
16 changes: 15 additions & 1 deletion src/lib/list/selection-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
forwardRef,
Inject,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
Expand Down Expand Up @@ -96,6 +97,7 @@ export class MatListOption extends _MatListOptionMixinBase

private _selected = false;
private _disabled = false;
private _parentStateSubscription: Subscription;

/** Whether the option has focus. */
_hasFocus: boolean = false;
Expand Down Expand Up @@ -140,6 +142,9 @@ export class MatListOption extends _MatListOptionMixinBase
/** @docs-private */
@Inject(forwardRef(() => MatSelectionList)) public selectionList: MatSelectionList) {
super();

this._parentStateSubscription = this.selectionList._stateChanges
.subscribe(() => this._changeDetector.markForCheck());
}

ngOnInit() {
Expand Down Expand Up @@ -172,6 +177,7 @@ export class MatListOption extends _MatListOptionMixinBase
}

this.selectionList._removeOptionFromList(this);
this._parentStateSubscription.unsubscribe();
}

/** Toggles the selection state of the option. */
Expand Down Expand Up @@ -265,11 +271,14 @@ export class MatListOption extends _MatListOptionMixinBase
changeDetection: ChangeDetectionStrategy.OnPush
})
export class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption,
CanDisable, CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy {
CanDisable, CanDisableRipple, AfterContentInit, ControlValueAccessor, OnDestroy, OnChanges {

/** The FocusKeyManager which handles focus. */
_keyManager: FocusKeyManager<MatListOption>;

/** Used to notify any child components listening to state changes. */
readonly _stateChanges = new EventEmitter<void>();

/** The option components contained within this selection-list. */
@ContentChildren(MatListOption) options: QueryList<MatListOption>;

Expand All @@ -296,6 +305,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. */
Expand Down Expand Up @@ -335,6 +345,10 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
});
}

ngOnChanges() {
this._stateChanges.next();
}

ngOnDestroy() {
this._modelChanges.unsubscribe();
}
Expand Down

0 comments on commit b3977d0

Please sign in to comment.