fix(selection-list): repeated preselected items not appearing as selected with OnPush parent (#10100)

Fixes preselected options, rendered with via `NgFor`, inside a component with `OnPush` change detection, not appearing as selected.

Fixes #10090.
This commit is contained in:
Kristiyan Kostadinov
2018-02-26 15:56:07 +01:00
committed by Jeremy Elbourn
parent a27d9dfffc
commit cdd224a2ca
2 changed files with 45 additions and 11 deletions
+32 -3
View File
@@ -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: `
<mat-selection-list [formControl]="formControl">
<mat-list-option *ngFor="let opt of opts" [value]="opt">{{opt}}</mat-list-option>
</mat-selection-list>
`
})
class SelectionListWithPreselectedFormControlOnPush {
opts = ['opt1', 'opt2', 'opt3'];
formControl = new FormControl(['opt2']);
}
+13 -8
View File
@@ -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() {