Skip to content

Commit

Permalink
fix(selection-list): repeated preselected items not appearing as sele…
Browse files Browse the repository at this point in the history
…cted with OnPush parent (angular#10100)

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

Fixes angular#10090.
  • Loading branch information
crisbeto authored and mmalerba committed Feb 26, 2018
1 parent 2ece359 commit 75c6195
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 11 deletions.
35 changes: 32 additions & 3 deletions src/lib/list/selection-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -592,7 +592,8 @@ describe('MatSelectionList with forms', () => {
SelectionListWithModel,
SelectionListWithFormControl,
SelectionListWithPreselectedOption,
SelectionListWithPreselectedOptionAndModel
SelectionListWithPreselectedOptionAndModel,
SelectionListWithPreselectedFormControlOnPush,
]
});

Expand Down Expand Up @@ -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();
}));

});
});

Expand Down Expand Up @@ -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']);
}
21 changes: 13 additions & 8 deletions src/lib/list/selection-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit 75c6195

Please sign in to comment.