添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hi, I want to use typeahead with http but I get an error which is "options.slice is not a function".Please Help Me

@Injectable()
export class UserService {
  constructor(private http: Http ) { }
  getAllUsers(email: string): Observable <any>{
    let params = new URLSearchParams();
    params.set('email', email);
    return this.http.get("http://localhost:8080/user/list",{ search: params })
      .map((res:Response) => this.extractData );
  private extractData(res: Response) {
    let body = res.json();
    return body || { };
@Component({
  selector: 'app-device-add',
  templateUrl: './device-add.component.html',
  styleUrls: ['./device-add.component.scss']
export class DeviceAddComponent implements OnInit {
  ngOnInit(){}
  public asyncSelected:string = '';
    public statesComplex:Array<any>;
  public dataSource: Observable<any>;
  public typeaheadLoading:boolean = false;
  public typeaheadNoResults:boolean = false;
  public constructor(private userService: UserService) {
    this.dataSource = Observable.create((observer:any) => {
      this.userService.getAllUsers(this.asyncSelected)
        .subscribe((result: any) => {
          observer.next(result);
  public changeTypeaheadLoading(e:boolean):void {
    this.typeaheadLoading = e;
  public changeTypeaheadNoResults(e:boolean):void {
    this.typeaheadNoResults = e;
  public typeaheadOnSelect(e:TypeaheadMatch):void {
    console.log('Selected value: ', e.value);
<h4>Asynchronous results</h4>
                <pre class="card card-block card-header">Model: {{asyncSelected | json}}</pre>
                <input [(ngModel)]="asyncSelected"
                       [typeahead]="dataSource"
                       (typeaheadLoading)="changeTypeaheadLoading($event)"
                       (typeaheadNoResults)="changeTypeaheadNoResults($event)"
                       (typeaheadOnSelect)="typeaheadOnSelect($event)"
                       [typeaheadOptionsLimit]="1"
                       [typeaheadOptionField]="'email'"
                       placeholder="Locations loaded with timeout"
                       class="form-control">
                <div *ngIf="typeaheadLoading===true">
                  <i class="glyphicon glyphicon-refresh ng-hide" style=""></i>
                <div *ngIf="typeaheadNoResults===true" class="" style="">
                  <i class="glyphicon glyphicon-remove"></i> No Results Found
          

@valorkin

Hi everyone, I have the same issue with the same syntax. Tried several ways to do it.
I skipped some of the methods/properties in order to make it more clear.

Note: The service returns the array of Schools and component successfully subscribes to it.
When observer.next(result); is executed, the Error gets thrown: EXCEPTION: options.slice is not a function

NOTE 2: I know that in Angular RC4, we had to have a hack to make it work with the service that gets the data for typeahead. The hack was as follows:

The HTML markup
<input [disabled]="!IsFormAuthorized" id="School" name="School" [(ngModel)]="asyncSelected" [typeahead]="autoCompleteRef"

Component code (
public autoCompleteRef = this.getAsyncData.bind(this); //getAsynData returned promise <School[]>

May be something similar can be done with the service that returns observable?

core.umd.js:3010 TypeError: options.slice is not a function
at TypeaheadDirective.prepareMatches (ng2-bootstrap.umd.js:5376)
at TypeaheadDirective.finalizeAsyncCall (ng2-bootstrap.umd.js:5358)
at SafeSubscriber.eval [as _next] (ng2-bootstrap.umd.js:5314)
at SafeSubscriber.__tryOrUnsub (Subscriber.ts:238)
at SafeSubscriber.next (Subscriber.ts:190)
at Subscriber._next (Subscriber.ts:135)
at Subscriber.next (Subscriber.ts:95)
at MergeMapSubscriber.notifyNext (mergeMap.ts:144)
at InnerSubscriber._next (InnerSubscriber.ts:17)
at InnerSubscriber.Subscriber.next (Subscriber.ts:95)ErrorHandler.handleError @ core.umd.js:3010next @ core.umd.js:6654schedulerFn @ core.umd.js:5952SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subject.next @ Subject.ts:61EventEmitter.emit @ core.umd.js:5944NgZone.triggerError @ core.umd.js:6248onHandleError @ core.umd.js:6227ZoneDelegate.handleError @ zone.js:207Zone.runTask @ zone.js:139ZoneTask.invoke @ zone.js:304
Subscriber.ts:241 Uncaught TypeError: options.slice is not a functionTypeaheadDirective.prepareMatches @ ng2-bootstrap.umd.js:5376TypeaheadDirective.finalizeAsyncCall @ ng2-bootstrap.umd.js:5358(anonymous function) @ ng2-bootstrap.umd.js:5314SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95MergeMapSubscriber.notifyNext @ mergeMap.ts:144InnerSubscriber._next @ InnerSubscriber.ts:17Subscriber.next @ Subscriber.ts:95(anonymous function) @ locations.component.ts:226SafeSubscriber.__tryOrUnsub @ Subscriber.ts:238SafeSubscriber.next @ Subscriber.ts:190Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95MapSubscriber._next @ map.ts:84Subscriber.next @ Subscriber.ts:95Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95Subscriber._next @ Subscriber.ts:135Subscriber.next @ Subscriber.ts:95onLoad @ http.umd.js:1083ZoneDelegate.invokeTask @ zone.js:236onInvokeTask @ core.umd.js:6197ZoneDelegate.invokeTask @ zone.js:235Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304

MY CODE SAMPLE

Module Code Snippet

`import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { TypeaheadModule } from 'ng2-bootstrap/ng2-bootstrap';

//component and routing module
import { LocationsComponent } from './locations.component';
import { LocationsRoutingModule } from './locations-routing.module';
import { SchoolService } from '../school/schoolService';

@NgModule({
imports: [
CommonModule,
LocationsRoutingModule,
FormsModule,
TypeaheadModule
declarations: [
LocationsComponent
providers: [
SchoolService
exports: [CommonModule]
export class LocationsModule { }`

Component Code Snippet
@component({
selector: 'locations-form',
templateUrl: './locations.html'
export class LocationsComponent implements OnInit {
` public dataSource: Observable;

constructor(private _schoolService: SchoolService,) {
this.dataSource = Observable.create((observer: any) => {
return this._schoolService.getSchools4(this.asyncSelected)
.subscribe((result: any) => {
observer.next(result); //this line fails; result contains array of schools

HTML Template Code Snippet
<input [disabled]="!IsFormAuthorized" id="School" name="School" [(ngModel)]="asyncSelected" [typeahead]="dataSource" [typeaheadOptionField]="'Name'" (typeaheadLoading)="changeTypeaheadLoading($event)" (typeaheadNoResults)="changeTypeaheadNoResults($event)" (typeaheadOnSelect)="typeaheadOnSelect($event)" class="form-control" required>

Service Code Snippet
` getSchools4(query: string): Observable {
return this.http.get(this._userAPIUrl + '/' + query)
.map(this.extractData)
.catch(this.handleError);
private extractData(res: Response) {
let body = res.json();
return body || {};

private handleError(error: Response) {
    // in a real world app, we may send the error to some remote logging infrastructure
    // instead of just logging it to the console
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');

School Class Code Snippet
export class School { constructor( public OrganizationId: number, public Name: string ) { } }

I don't think you have your data source setup properly. From the documentation

this.dataSource = Observable.create((observer:any) => {
    // Runs on every search
    // asyncSelected is a component variable bound to [(ngModel)]
    // when user types into the input .next is called with the value from the input
    observer.next(this.asyncSelected);
}).mergeMap((term: string) => this.myAsyncDataService.search(term));

Make sure you have that last mergeMap and that your service returns an array.

In case this will help others... I was also receiving "options.slice is not a function", and the issue was the way I implemented the async service returning my array of objects in Angular4.

I forgot to map my response to json in the service (Angular1 habits die hard) like this:

getList(listName:string, query:string): Observable<any> { return this.http.get(${this.apiUrl}/${listName}?query=${query}); }

Once I changed it to this, the "options.slice" problem was resolved.
getList(listName:string, query:string): Observable<any> { return this.http.get(${this.apiUrl}/${listName}?query=${query}) .map((res: Response) => res.json()) .catch((error:any) => Observable.throw(error.json().error || 'Server error')); }

I checked in the ngx-bootstrap library typeahead.directive.js line 259, and noticed that the limited variable was just a truncated string like '[{ "foo:', and realized the response was not converted to a json object, but was merely a string.

Following @avalonabecker, here's another example

getStatesAsObservable(token: string): Observable<any> {
    const query = new RegExp(token, 'ig');
    const fn = () => {
      return new Observable((observer) => {
        setTimeout(() => {
          const res = this.statesComplex.filter((state: any) => {
            return query.test(state.name);
          observer.next(res);
        }, 1000);
    return fn();