mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(autocomplete): panel not being shown with delay and OnPush change detection (#3977)
Fixes #3955.
This commit is contained in:
committed by
Kara
parent
4bfd2a387c
commit
efd348512f
@@ -1,5 +1,13 @@
|
||||
import {TestBed, async, fakeAsync, tick, ComponentFixture} from '@angular/core/testing';
|
||||
import {Component, OnDestroy, QueryList, ViewChild, ViewChildren} from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
OnDestroy,
|
||||
QueryList,
|
||||
ViewChild,
|
||||
ViewChildren,
|
||||
ChangeDetectionStrategy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import {By} from '@angular/platform-browser';
|
||||
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {MdAutocompleteModule, MdAutocompleteTrigger} from './index';
|
||||
@@ -38,7 +46,8 @@ describe('MdAutocomplete', () => {
|
||||
SimpleAutocomplete,
|
||||
AutocompleteWithoutForms,
|
||||
NgIfAutocomplete,
|
||||
AutocompleteWithNgModel
|
||||
AutocompleteWithNgModel,
|
||||
AutocompleteWithOnPushDelay
|
||||
],
|
||||
providers: [
|
||||
{provide: OverlayContainer, useFactory: () => {
|
||||
@@ -1090,6 +1099,24 @@ describe('MdAutocomplete', () => {
|
||||
expect(Math.ceil(parseFloat(overlayPane.style.width))).toEqual(500);
|
||||
|
||||
});
|
||||
|
||||
it('should show the panel when the options are initialized later within a component with ' +
|
||||
'OnPush change detection', fakeAsync(() => {
|
||||
let fixture = TestBed.createComponent(AutocompleteWithOnPushDelay);
|
||||
|
||||
fixture.detectChanges();
|
||||
dispatchFakeEvent(fixture.debugElement.query(By.css('input')).nativeElement, 'focus');
|
||||
tick(1000);
|
||||
fixture.detectChanges();
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
let panel = overlayContainerElement.querySelector('.mat-autocomplete-panel') as HTMLElement;
|
||||
let visibleClass = 'mat-autocomplete-visible';
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(panel.classList).toContain(visibleClass, `Expected panel to be visible.`);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
@Component({
|
||||
@@ -1239,6 +1266,30 @@ class AutocompleteWithNgModel {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `
|
||||
<md-input-container>
|
||||
<input type="text" mdInput [mdAutocomplete]="auto">
|
||||
</md-input-container>
|
||||
|
||||
<md-autocomplete #auto="mdAutocomplete">
|
||||
<md-option *ngFor="let option of options" [value]="option">{{ option }}</md-option>
|
||||
</md-autocomplete>
|
||||
`
|
||||
})
|
||||
class AutocompleteWithOnPushDelay implements OnInit {
|
||||
options: string[];
|
||||
|
||||
ngOnInit() {
|
||||
setTimeout(() => {
|
||||
this.options = ['One'];
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** This is a mock keyboard event to test keyboard events in the autocomplete. */
|
||||
class MockKeyboardEvent {
|
||||
constructor(public keyCode: number) {}
|
||||
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
QueryList,
|
||||
TemplateRef,
|
||||
ViewChild,
|
||||
ViewEncapsulation
|
||||
ViewEncapsulation,
|
||||
ChangeDetectorRef,
|
||||
} from '@angular/core';
|
||||
import {MdOption} from '../core';
|
||||
import {ActiveDescendantKeyManager} from '../core/a11y/activedescendant-key-manager';
|
||||
@@ -52,6 +53,8 @@ export class MdAutocomplete implements AfterContentInit {
|
||||
/** Unique ID to be used by autocomplete trigger's "aria-owns" property. */
|
||||
id: string = `md-autocomplete-${_uniqueAutocompleteIdCounter++}`;
|
||||
|
||||
constructor(private _changeDetectorRef: ChangeDetectorRef) { }
|
||||
|
||||
ngAfterContentInit() {
|
||||
this._keyManager = new ActiveDescendantKeyManager(this.options).withWrap();
|
||||
}
|
||||
@@ -68,7 +71,10 @@ export class MdAutocomplete implements AfterContentInit {
|
||||
|
||||
/** Panel should hide itself when the option list is empty. */
|
||||
_setVisibility() {
|
||||
Promise.resolve().then(() => this.showPanel = !!this.options.length);
|
||||
Promise.resolve().then(() => {
|
||||
this.showPanel = !!this.options.length;
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/** Sets a class on the panel based on its position (used to set y-offset). */
|
||||
|
||||
Reference in New Issue
Block a user