mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
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:
committed by
Jeremy Elbourn
parent
a27d9dfffc
commit
cdd224a2ca
@@ -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']);
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user