diff --git a/demo/src/ng-api-doc.ts b/demo/src/ng-api-doc.ts
index 7d2dc88bc4..9991450319 100644
--- a/demo/src/ng-api-doc.ts
+++ b/demo/src/ng-api-doc.ts
@@ -3869,7 +3869,7 @@ export const ngdoc: any = {
},
{
"name": "typeahead",
- "type": "any",
+ "type": "Typeahead",
"description": "
options source, can be Array of strings, objects or\nan Observable for external matching process
\n"
},
{
diff --git a/src/typeahead/typeahead.directive.ts b/src/typeahead/typeahead.directive.ts
index d97963da1a..60c588c454 100644
--- a/src/typeahead/typeahead.directive.ts
+++ b/src/typeahead/typeahead.directive.ts
@@ -15,7 +15,7 @@ import {
} from '@angular/core';
import { NgControl } from '@angular/forms';
-import { from, Subscription, isObservable } from 'rxjs';
+import { from, Subscription, isObservable, Observable } from 'rxjs';
import { ComponentLoader, ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
import { debounceTime, filter, mergeMap, switchMap, toArray } from 'rxjs/operators';
@@ -25,13 +25,15 @@ import { TypeaheadConfig } from './typeahead.config';
import { getValueFromObject, latinize, tokenize } from './typeahead-utils';
import { TypeaheadOrder } from './typeahead-order.class';
+type TypeaheadOption = string | {[key in string | number]: any};
+type Typeahead = TypeaheadOption[] | Observable;
+
@Directive({selector: '[typeahead]', exportAs: 'bs-typeahead'})
export class TypeaheadDirective implements OnInit, OnDestroy {
/** options source, can be Array of strings, objects or
* an Observable for external matching process
*/
- // tslint:disable-next-line:no-any
- @Input() typeahead: any;
+ @Input() typeahead: Typeahead;
/** minimal no of characters that needs to be entered before
* typeahead kicks-in. When set to 0, typeahead shows on focus with full
* list of options (limited as normal by typeaheadOptionsLimit)
@@ -115,8 +117,7 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
/** fired when option was selected, return object with data of this option */
@Output() typeaheadOnSelect = new EventEmitter();
/** fired when blur event occurs. returns the active item */
- // tslint:disable-next-line:no-any
- @Output() typeaheadOnBlur = new EventEmitter();
+ @Output() typeaheadOnBlur = new EventEmitter();
/**
* A selector specifying the element the typeahead should be appended to.
@@ -142,15 +143,13 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
_container: TypeaheadContainerComponent;
isActiveItemChanged = false;
- isTypeaheadOptionsListActive = false;
isFocused = false;
cancelRequestOnFocusLost = false;
// tslint:disable-next-line:no-any
- protected keyUpEventEmitter: EventEmitter = new EventEmitter();
+ protected keyUpEventEmitter: EventEmitter = new EventEmitter();
protected _matches: TypeaheadMatch[];
protected placement = 'bottom-left';
- // protected popup:ComponentRef;
private _typeahead: ComponentLoader;
private _subscriptions: Subscription[] = [];
@@ -195,10 +194,7 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
this.typeaheadWaitMs = this.typeaheadWaitMs || 0;
// async should be false in case of array
- if (
- this.typeaheadAsync === undefined &&
- !(isObservable(this.typeahead))
- ) {
+ if (this.typeaheadAsync === undefined && !(isObservable(this.typeahead))) {
this.typeaheadAsync = false;
}
@@ -399,10 +395,10 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
this._subscriptions.push(
this.keyUpEventEmitter
.pipe(
- debounceTime(this.typeaheadWaitMs),
+ debounceTime(this.typeaheadWaitMs),
switchMap(() => this.typeahead)
)
- .subscribe((matches: any[]) => {
+ .subscribe((matches: TypeaheadOption[]) => {
this.finalizeAsyncCall(matches);
})
);
@@ -412,27 +408,26 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
this._subscriptions.push(
this.keyUpEventEmitter
.pipe(
- debounceTime(this.typeaheadWaitMs),
+ debounceTime(this.typeaheadWaitMs),
mergeMap((value: string) => {
const normalizedQuery = this.normalizeQuery(value);
return from(this.typeahead)
.pipe(
- filter((option: any) => {
+ filter((option: TypeaheadOption) => {
return option && this.testMatch(this.normalizeOption(option), normalizedQuery);
}),
toArray()
);
})
)
- .subscribe((matches: any[]) => {
+ .subscribe((matches: TypeaheadOption[]) => {
this.finalizeAsyncCall(matches);
})
);
}
- // tslint:disable-next-line:no-any
- protected normalizeOption(option: any): any {
+ protected normalizeOption(option: TypeaheadOption): string {
const optionValue: string = getValueFromObject(
option,
this.typeaheadOptionField
@@ -445,8 +440,7 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
}
protected normalizeQuery(value: string): string | string[] {
- // If singleWords, break model here to not be doing extra work on each
- // iteration
+ // If singleWords, break model here to not be doing extra work on each iteration
let normalizedQuery: string | string[] = (this.typeaheadLatinize
? latinize(value)
: value)
@@ -480,7 +474,7 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
return match.indexOf(test) >= 0;
}
- protected finalizeAsyncCall(matches: any[]): void {
+ protected finalizeAsyncCall(matches: TypeaheadOption[]): void {
this.prepareMatches(matches || []);
this.typeaheadLoading.emit(false);
@@ -518,7 +512,7 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
}
}
- protected prepareMatches(options: any[]): void {
+ protected prepareMatches(options: TypeaheadOption[]): void {
const limited = options.slice(0, this.typeaheadOptionsLimit);
const sorted = !this.typeaheadOrderBy ? limited : this.orderMatches(limited);
@@ -539,18 +533,14 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
// add each item of group to array of matches
matches = matches.concat(
sorted
- .filter(
- // tslint:disable-next-line:no-any
- (option: any) =>
- getValueFromObject(option, this.typeaheadGroupField) === group
+ .filter((option: TypeaheadOption) =>
+ getValueFromObject(option, this.typeaheadGroupField) === group
)
- .map(
- // tslint:disable-next-line:no-any
- (option: any) =>
- new TypeaheadMatch(
- option,
- getValueFromObject(option, this.typeaheadOptionField)
- )
+ .map((option: TypeaheadOption) =>
+ new TypeaheadMatch(
+ option,
+ getValueFromObject(option, this.typeaheadOptionField)
+ )
)
);
});
@@ -568,7 +558,7 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
}
}
- protected orderMatches(options: T[]): T[] {
+ protected orderMatches(options: TypeaheadOption[]): TypeaheadOption[] {
if (!options.length) {
return options;
}
@@ -603,7 +593,7 @@ export class TypeaheadDirective implements OnInit, OnDestroy {
return options;
}
- return options.sort((a: T, b: T) => {
+ return options.sort((a: TypeaheadOption, b: TypeaheadOption) => {
const stringA = getValueFromObject(a, field);
const stringB = getValueFromObject(b, field);