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);