Skip to content

Commit 819fa0b

Browse files
crisbetotinayuangao
authored andcommitted
fix(select): initial value not being displayed with FormControl and OnPush (#3434)
* fix(select): initial value not being displayed with FormControl and OnPush Fixes the initial value not being displayed in a select that has a `FormControl` and is placed in a component with `ChangeDetectionStrategy.onPush`. Relates to #2269 (comment). * chore: remove unused properties
1 parent d06ad75 commit 819fa0b

File tree

2 files changed

+41
-21
lines changed

2 files changed

+41
-21
lines changed

src/lib/select/select.spec.ts

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ describe('MdSelect', () => {
3939
FloatPlaceholderSelect,
4040
SelectWithErrorSibling,
4141
ThrowsErrorOnInit,
42-
BasicSelectOnPush
42+
BasicSelectOnPush,
43+
BasicSelectOnPushPreselected
4344
],
4445
providers: [
4546
{provide: OverlayContainer, useFactory: () => {
@@ -1322,16 +1323,25 @@ describe('MdSelect', () => {
13221323
});
13231324

13241325
describe('with OnPush change detection', () => {
1325-
let fixture: ComponentFixture<BasicSelectOnPush>;
1326-
let trigger: HTMLElement;
1326+
it('should set the trigger text based on the value when initialized', async(() => {
1327+
let fixture = TestBed.createComponent(BasicSelectOnPushPreselected);
13271328

1328-
beforeEach(() => {
1329-
fixture = TestBed.createComponent(BasicSelectOnPush);
13301329
fixture.detectChanges();
1331-
trigger = fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement;
1332-
});
1330+
1331+
fixture.whenStable().then(() => {
1332+
let trigger = fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement;
1333+
1334+
fixture.detectChanges();
1335+
1336+
expect(trigger.textContent).toContain('Pizza');
1337+
});
1338+
}));
13331339

13341340
it('should update the trigger based on the value', () => {
1341+
let fixture = TestBed.createComponent(BasicSelectOnPush);
1342+
fixture.detectChanges();
1343+
let trigger = fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement;
1344+
13351345
fixture.componentInstance.control.setValue('pizza-1');
13361346
fixture.detectChanges();
13371347

@@ -1342,7 +1352,9 @@ describe('MdSelect', () => {
13421352

13431353
expect(trigger.textContent).not.toContain('Pizza');
13441354
});
1355+
13451356
});
1357+
13461358
});
13471359

13481360

@@ -1561,9 +1573,26 @@ class BasicSelectOnPush {
15611573
{ value: 'tacos-2', viewValue: 'Tacos' },
15621574
];
15631575
control = new FormControl();
1576+
}
15641577

1565-
@ViewChild(MdSelect) select: MdSelect;
1566-
@ViewChildren(MdOption) options: QueryList<MdOption>;
1578+
@Component({
1579+
selector: 'basic-select-on-push-preselected',
1580+
changeDetection: ChangeDetectionStrategy.OnPush,
1581+
template: `
1582+
<md-select placeholder="Food" [formControl]="control">
1583+
<md-option *ngFor="let food of foods" [value]="food.value">
1584+
{{ food.viewValue }}
1585+
</md-option>
1586+
</md-select>
1587+
`
1588+
})
1589+
class BasicSelectOnPushPreselected {
1590+
foods: any[] = [
1591+
{ value: 'steak-0', viewValue: 'Steak' },
1592+
{ value: 'pizza-1', viewValue: 'Pizza' },
1593+
{ value: 'tacos-2', viewValue: 'Tacos' },
1594+
];
1595+
control = new FormControl('pizza-1');
15671596
}
15681597

15691598
@Component({

src/lib/select/select.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,6 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
313313
writeValue(value: any): void {
314314
if (this.options) {
315315
this._setSelectionByValue(value);
316-
this._changeDetectorRef.markForCheck();
317316
}
318317
}
319318

@@ -430,17 +429,9 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
430429
* found with the designated value, the select trigger is cleared.
431430
*/
432431
private _setSelectionByValue(value: any): void {
433-
const options = this.options.toArray();
434-
435-
for (let i = 0; i < this.options.length; i++) {
436-
if (options[i].value === value) {
437-
options[i].select();
438-
return;
439-
}
440-
}
441-
442-
// Clear selection if no item was selected.
443-
this._clearSelection();
432+
const correspondingOption = this.options.find(option => option.value === value);
433+
correspondingOption ? correspondingOption.select() : this._clearSelection();
434+
this._changeDetectorRef.markForCheck();
444435
}
445436

446437
/** Clears the select trigger and deselects every option in the list. */

0 commit comments

Comments
 (0)