diff --git a/src/lib/list/selection-list.spec.ts b/src/lib/list/selection-list.spec.ts index 78ae7f59716c..d58b8f5728cc 100644 --- a/src/lib/list/selection-list.spec.ts +++ b/src/lib/list/selection-list.spec.ts @@ -5,8 +5,8 @@ import { dispatchEvent, dispatchKeyboardEvent, } from '@angular/cdk/testing'; -import {Component, DebugElement} from '@angular/core'; -import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; +import {Component, DebugElement, ChangeDetectionStrategy} from '@angular/core'; +import {async, ComponentFixture, fakeAsync, TestBed, tick, flush} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import { MatListModule, @@ -592,7 +592,8 @@ describe('MatSelectionList with forms', () => { SelectionListWithModel, SelectionListWithFormControl, SelectionListWithPreselectedOption, - SelectionListWithPreselectedOptionAndModel + SelectionListWithPreselectedOptionAndModel, + SelectionListWithPreselectedFormControlOnPush, ] }); @@ -800,6 +801,20 @@ describe('MatSelectionList with forms', () => { expect(fixture.componentInstance.selectedOptions).toEqual(['opt1', 'opt2']); })); + it('should show the item as selected when preselected inside OnPush parent', fakeAsync(() => { + const fixture = TestBed.createComponent(SelectionListWithPreselectedFormControlOnPush); + fixture.detectChanges(); + + const option = fixture.debugElement.queryAll(By.directive(MatListOption))[1]; + + fixture.detectChanges(); + flush(); + fixture.detectChanges(); + + expect(option.componentInstance.selected).toBe(true); + expect(option.nativeElement.querySelector('.mat-pseudo-checkbox-checked')).toBeTruthy(); + })); + }); }); @@ -949,3 +964,17 @@ class SelectionListWithPreselectedOption { class SelectionListWithPreselectedOptionAndModel { selectedOptions = ['opt1']; } + + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` + + {{opt}} + + ` +}) +class SelectionListWithPreselectedFormControlOnPush { + opts = ['opt1', 'opt2', 'opt3']; + formControl = new FormControl(['opt2']); +} diff --git a/src/lib/list/selection-list.ts b/src/lib/list/selection-list.ts index 9fd7742042bb..8e5943d1765c 100644 --- a/src/lib/list/selection-list.ts +++ b/src/lib/list/selection-list.ts @@ -168,14 +168,19 @@ export class MatListOption extends _MatListOptionMixinBase } ngOnInit() { - if (this._selected) { - // List options that are selected at initialization can't be reported properly to the form - // control. This is because it takes some time until the selection-list knows about all - // available options. Also it can happen that the ControlValueAccessor has an initial value - // that should be used instead. Deferring the value change report to the next tick ensures - // that the form control value is not being overwritten. - Promise.resolve().then(() => this.selected = true); - } + // List options that are selected at initialization can't be reported properly to the form + // control. This is because it takes some time until the selection-list knows about all + // available options. Also it can happen that the ControlValueAccessor has an initial value + // that should be used instead. Deferring the value change report to the next tick ensures + // that the form control value is not being overwritten. + const wasSelected = this._selected; + + Promise.resolve().then(() => { + if (this._selected || wasSelected) { + this.selected = true; + this._changeDetector.markForCheck(); + } + }); } ngAfterContentInit() {