mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(select): view not updating when using OnPush detection strategy (#2894)
Fixes the select's view not being updated when the value is set through a component that has its change detection set to `OnPush`. Fixes #2663. Fixes #2269.
This commit is contained in:
committed by
tinayuangao
parent
1a89a08f1c
commit
3bcb7c3314
@@ -1,6 +1,13 @@
|
||||
import {TestBed, async, ComponentFixture, fakeAsync, tick} from '@angular/core/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {Component, DebugElement, QueryList, ViewChild, ViewChildren} from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
DebugElement,
|
||||
QueryList,
|
||||
ViewChild,
|
||||
ViewChildren,
|
||||
ChangeDetectionStrategy,
|
||||
} from '@angular/core';
|
||||
import {MdSelectModule} from './index';
|
||||
import {OverlayContainer} from '../core/overlay/overlay-container';
|
||||
import {MdSelect} from './select';
|
||||
@@ -26,7 +33,8 @@ describe('MdSelect', () => {
|
||||
SelectInitWithoutOptions,
|
||||
SelectWithChangeEvent,
|
||||
CustomSelectAccessor,
|
||||
CompWithCustomSelect
|
||||
CompWithCustomSelect,
|
||||
BasicSelectOnPush
|
||||
],
|
||||
providers: [
|
||||
{provide: OverlayContainer, useFactory: () => {
|
||||
@@ -1255,6 +1263,29 @@ describe('MdSelect', () => {
|
||||
expect(fixture.componentInstance.changeListener).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with OnPush change detection', () => {
|
||||
let fixture: ComponentFixture<BasicSelectOnPush>;
|
||||
let trigger: HTMLElement;
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(BasicSelectOnPush);
|
||||
fixture.detectChanges();
|
||||
trigger = fixture.debugElement.query(By.css('.md-select-trigger')).nativeElement;
|
||||
});
|
||||
|
||||
it('should update the trigger based on the value', () => {
|
||||
fixture.componentInstance.control.setValue('pizza-1');
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(trigger.textContent).toContain('Pizza');
|
||||
|
||||
fixture.componentInstance.control.reset();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(trigger.textContent).not.toContain('Pizza');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@Component({
|
||||
@@ -1433,6 +1464,29 @@ class CompWithCustomSelect {
|
||||
@ViewChild(CustomSelectAccessor) customAccessor: CustomSelectAccessor;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'basic-select-on-push',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `
|
||||
<md-select placeholder="Food" [formControl]="control">
|
||||
<md-option *ngFor="let food of foods" [value]="food.value">
|
||||
{{ food.viewValue }}
|
||||
</md-option>
|
||||
</md-select>
|
||||
`
|
||||
})
|
||||
class BasicSelectOnPush {
|
||||
foods: any[] = [
|
||||
{ value: 'steak-0', viewValue: 'Steak' },
|
||||
{ value: 'pizza-1', viewValue: 'Pizza' },
|
||||
{ value: 'tacos-2', viewValue: 'Tacos' },
|
||||
];
|
||||
control = new FormControl();
|
||||
|
||||
@ViewChild(MdSelect) select: MdSelect;
|
||||
@ViewChildren(MdOption) options: QueryList<MdOption>;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO: Move this to core testing utility until Angular has event faking
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
Self,
|
||||
ViewEncapsulation,
|
||||
ViewChild,
|
||||
ChangeDetectorRef,
|
||||
} from '@angular/core';
|
||||
import {MdOption, MdOptionSelectEvent} from '../core/option/option';
|
||||
import {ENTER, SPACE} from '../core/keyboard/keycodes';
|
||||
@@ -233,8 +234,8 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
|
||||
@Output() change: EventEmitter<MdSelectChange> = new EventEmitter<MdSelectChange>();
|
||||
|
||||
constructor(private _element: ElementRef, private _renderer: Renderer,
|
||||
private _viewportRuler: ViewportRuler, @Optional() private _dir: Dir,
|
||||
@Self() @Optional() public _control: NgControl) {
|
||||
private _viewportRuler: ViewportRuler, private _changeDetectorRef: ChangeDetectorRef,
|
||||
@Optional() private _dir: Dir, @Self() @Optional() public _control: NgControl) {
|
||||
if (this._control) {
|
||||
this._control.valueAccessor = this;
|
||||
}
|
||||
@@ -301,6 +302,7 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
|
||||
}
|
||||
|
||||
this._setSelectionByValue(value);
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user