Skip to content

Commit a2ba68a

Browse files
fix(typeahead): properly handle components using OnPush strategy
Fixes #775
1 parent 7d4a455 commit a2ba68a

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

src/typeahead/typeahead.spec.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import {TestBed, ComponentFixture, async, inject} from '@angular/core/testing';
1+
import {TestBed, ComponentFixture, async, fakeAsync, inject, tick} from '@angular/core/testing';
22
import {createGenericTestComponent, isBrowser} from '../test/common';
33
import {expectResults, getWindowLinks} from '../test/typeahead/common';
44

5-
import {Component, DebugElement, ViewChild} from '@angular/core';
5+
import {Component, DebugElement, ViewChild, ChangeDetectionStrategy} from '@angular/core';
66
import {Validators, FormControl, FormGroup, FormsModule, ReactiveFormsModule} from '@angular/forms';
77
import {By} from '@angular/platform-browser';
88
import {Observable} from 'rxjs/Rx';
99
import 'rxjs/add/operator/map';
10+
import 'rxjs/add/operator/debounceTime';
1011

1112
import {NgbTypeahead} from './typeahead';
1213
import {NgbTypeaheadModule} from './typeahead.module';
@@ -15,6 +16,9 @@ import {NgbTypeaheadConfig} from './typeahead-config';
1516
const createTestComponent = (html: string) =>
1617
createGenericTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
1718

19+
const createOnPushTestComponent = (html: string) =>
20+
createGenericTestComponent(html, TestOnPushComponent) as ComponentFixture<TestOnPushComponent>;
21+
1822
enum Key {
1923
Tab = 9,
2024
Enter = 13,
@@ -62,8 +66,10 @@ function expectWindowResults(element, expectedResults: string[]) {
6266
describe('ngb-typeahead', () => {
6367

6468
beforeEach(() => {
65-
TestBed.configureTestingModule(
66-
{declarations: [TestComponent], imports: [NgbTypeaheadModule, FormsModule, ReactiveFormsModule]});
69+
TestBed.configureTestingModule({
70+
declarations: [TestComponent, TestOnPushComponent],
71+
imports: [NgbTypeaheadModule, FormsModule, ReactiveFormsModule]
72+
});
6773
});
6874

6975
describe('valueaccessor', () => {
@@ -290,6 +296,15 @@ describe('ngb-typeahead', () => {
290296
expectWindowResults(compiled, ['+ONE', 'ONE MORE']);
291297
});
292298

299+
it('should properly display results when an owning components using OnPush strategy', fakeAsync(() => {
300+
const fixture = createOnPushTestComponent(`<input type="text" [(ngModel)]="model" [ngbTypeahead]="find"/>`);
301+
const compiled = fixture.nativeElement;
302+
303+
changeInput(compiled, 'o');
304+
fixture.detectChanges();
305+
tick(250);
306+
expectWindowResults(compiled, ['+one', 'one more']);
307+
}));
293308
});
294309

295310
describe('objects', () => {
@@ -588,3 +603,12 @@ class TestComponent {
588603

589604
onSelect($event) { this.selectEventValue = $event; }
590605
}
606+
607+
@Component({selector: 'test-onpush-cmp', changeDetection: ChangeDetectionStrategy.OnPush, template: ''})
608+
class TestOnPushComponent {
609+
private _strings = ['one', 'one more', 'two', 'three'];
610+
611+
find = (text$: Observable<string>) => {
612+
return text$.debounceTime(200).map(text => this._strings.filter(v => v.startsWith(text)));
613+
};
614+
}

src/typeahead/typeahead.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ export class NgbTypeahead implements ControlValueAccessor,
270270
this._windowRef.instance.resultTemplate = this.resultTemplate;
271271
}
272272
this._showHint();
273+
274+
// The observable stream we are subscribing to might have async steps
275+
// and if a component containing typeahead is using the OnPush strategy
276+
// the change detection turn wouldn't be invoked automatically.
277+
this._windowRef.changeDetectorRef.detectChanges();
273278
}
274279
});
275280
}

0 commit comments

Comments
 (0)