Search code examples
angularbootstrap-typeahead

Not able to populate data get from service in typeahead in Angular 4


I have input field, where it should suggest the usernames matched with the text typed in field. I am using ngx-bootsrap typeahead library.

The list of usernames has to be brought from API call running on backend. On every keystroke, it must call the API endpoint and get me back the matched results.

I tried the following way.

service.ts

search() : any{

this.req = this.http.get('/timesheet/user').subscribe(
  res => {
    return res;
  },
  (e) => {
    console.log('Error');
  },
  () => {
    this.loading = false;
    console.log('search completed');
  }
);

}

On every key stroke, I am calling the function loadData().

asyncSelected: string;
dataSource: Observable<any>;


loadData() {

   this.dataSource = Observable.create((observer: any) => {
      observer.next(this.asyncSelected);
    }).mergeMap((token: string) => {
      this.getStatesAsObservable(token);
    });
}


getStatesAsObservable(token: string): Observable<any> {
   let query = new RegExp(token, 'ig');

   return Observable.of(
     this.searchService.searchOb().filter((state: any) => {
     return query.test(state.name);
    })
  );
}

asyncSelected is the model binded with input field.

and when I tried to have the result of API call saved in a variable (Service) class. It worked fine. But I don't want it to be saved in a variable as the list can be huge and want to filter the results before populating it.

I ensured my service running fine.

Have a look at this: https://valor-software.com/ngx-bootstrap/#/typeahead#async-data


Solution

  • You should subscribe your http request in your component rather than in service. Yor service code should look like this:

    search() : Observable<any> {
       return this.http.get('/timesheet/user');
    }
    

    Now in your template use async pipe to get data. If you want to merge your data then do with mergeMap operator.

    Updating code with copied code from documentation of typehead

     <input [(ngModel)]="asyncSelected"
             [typeahead]="data$ | async"
             (typeaheadLoading)="changeTypeaheadLoading($event)"
             (typeaheadNoResults)="changeTypeaheadNoResults($event)"
             (typeaheadOnSelect)="typeaheadOnSelect($event)"
             [typeaheadOptionsLimit]="7"
             typeaheadOptionField="name"
             placeholder="Locations loaded with timeout"
             class="form-control">
    

    In component declare a property with name data$ of type Observable and assign your observable to this data$. Hope it will help