title: How to use ngx-bootstrap typeahead with async httpclient call
body: <p>I'm attempting to populate nxg-bootstrap typeahead with async results from a rest backend in Angular 4. Their site has an example (<a href="https://valor-software.com/ngx-bootstrap/#/typeahead" rel="noreferrer">https://valor-software.com/ngx-bootstrap/#/typeahead</a>) on how to do this with mock observable data, but I am struggling doing this with httpclient. All examples of people using this are using the old <code>Http</code> module instead of the new <code>HttpClient</code> module used in Angular 4. </p>
  
  <p>This is their example: </p>
  
  <pre><code>import { Component } from '@angular/core';
  
  import { Observable } from 'rxjs/Observable';
  import 'rxjs/add/observable/of';
  import { TypeaheadMatch } from 'ngx-bootstrap/typeahead';
  
  @Component({
    selector: 'demo-typeahead-async',
    templateUrl: './async.html'
  })
  export class DemoTypeaheadAsyncComponent {
    asyncSelected: string;
    typeaheadLoading: boolean;
    typeaheadNoResults: boolean;
    dataSource: Observable&lt;any&gt;;
    statesComplex: any[] = [
      { id: 1, name: 'Alabama', region: 'South' },
      { id: 2, name: 'Alaska', region: 'West' },
      {
        id: 3,
        name: 'Arizona',
        region: 'West'
      },
      { id: 4, name: 'Arkansas', region: 'South' },
      { id: 5, name: 'California', region: 'West' },
      { id: 6, name: 'Colorado', region: 'West' },
      { id: 7, name: 'Connecticut', region: 'Northeast' },
      { id: 8, name: 'Delaware', region: 'South' },
      { id: 9, name: 'Florida', region: 'South' },
      { id: 10, name: 'Georgia', region: 'South' },
      { id: 11, name: 'Hawaii', region: 'West' },
      { id: 12, name: 'Idaho', region: 'West' },
      { id: 13, name: 'Illinois', region: 'Midwest' },
      { id: 14, name: 'Indiana', region: 'Midwest' },
      { id: 15, name: 'Iowa', region: 'Midwest' },
      { id: 16, name: 'Kansas', region: 'Midwest' },
      { id: 17, name: 'Kentucky', region: 'South' },
      { id: 18, name: 'Louisiana', region: 'South' },
      { id: 19, name: 'Maine', region: 'Northeast' },
      { id: 21, name: 'Maryland', region: 'South' },
      { id: 22, name: 'Massachusetts', region: 'Northeast' },
      { id: 23, name: 'Michigan', region: 'Midwest' },
      { id: 24, name: 'Minnesota', region: 'Midwest' },
      { id: 25, name: 'Mississippi', region: 'South' },
      { id: 26, name: 'Missouri', region: 'Midwest' },
      { id: 27, name: 'Montana', region: 'West' },
      { id: 28, name: 'Nebraska', region: 'Midwest' },
      { id: 29, name: 'Nevada', region: 'West' },
      { id: 30, name: 'New Hampshire', region: 'Northeast' },
      { id: 31, name: 'New Jersey', region: 'Northeast' },
      { id: 32, name: 'New Mexico', region: 'West' },
      { id: 33, name: 'New York', region: 'Northeast' },
      { id: 34, name: 'North Dakota', region: 'Midwest' },
      { id: 35, name: 'North Carolina', region: 'South' },
      { id: 36, name: 'Ohio', region: 'Midwest' },
      { id: 37, name: 'Oklahoma', region: 'South' },
      { id: 38, name: 'Oregon', region: 'West' },
      { id: 39, name: 'Pennsylvania', region: 'Northeast' },
      { id: 40, name: 'Rhode Island', region: 'Northeast' },
      { id: 41, name: 'South Carolina', region: 'South' },
      { id: 42, name: 'South Dakota', region: 'Midwest' },
      { id: 43, name: 'Tennessee', region: 'South' },
      { id: 44, name: 'Texas', region: 'South' },
      { id: 45, name: 'Utah', region: 'West' },
      { id: 46, name: 'Vermont', region: 'Northeast' },
      { id: 47, name: 'Virginia', region: 'South' },
      { id: 48, name: 'Washington', region: 'South' },
      { id: 49, name: 'West Virginia', region: 'South' },
      { id: 50, name: 'Wisconsin', region: 'Midwest' },
      { id: 51, name: 'Wyoming', region: 'West' }
    ];
  
    constructor() {
      this.dataSource = Observable.create((observer: any) =&gt; {
        // Runs on every search
        observer.next(this.asyncSelected);
      }).mergeMap((token: string) =&gt; this.getStatesAsObservable(token));
    }
  
    getStatesAsObservable(token: string): Observable&lt;any&gt; {
      let query = new RegExp(token, 'ig');
  
      return Observable.of(
        this.statesComplex.filter((state: any) =&gt; {
          return query.test(state.name);
        })
      );
    }
  
    changeTypeaheadLoading(e: boolean): void {
      this.typeaheadLoading = e;
    }
  
    changeTypeaheadNoResults(e: boolean): void {
      this.typeaheadNoResults = e;
    }
  
    typeaheadOnSelect(e: TypeaheadMatch): void {
      console.log('Selected value: ', e.value);
    }
  }
  </code></pre>
  
  <p>With Template</p>
  
  <pre><code>&lt;pre class="card card-block card-header"&gt;Model: {{asyncSelected | json}}
  &lt;/pre&gt;
    &lt;input [(ngModel)]="asyncSelected"
           [typeahead]="dataSource"
           (typeaheadLoading)="changeTypeaheadLoading($event)"
           (typeaheadNoResults)="changeTypeaheadNoResults($event)"
           (typeaheadOnSelect)="typeaheadOnSelect($event)"
           [typeaheadOptionsLimit]="7"
           typeaheadOptionField="name"
           placeholder="Locations loaded with timeout"
           class="form-control"&gt;
    &lt;div *ngIf="typeaheadLoading===true"&gt;Loading&lt;/div&gt;
    &lt;div *ngIf="typeaheadNoResults===true"&gt;&amp;#10060; No Results Found&lt;/div&gt;
  </code></pre>
  
  <p>Here is my attempt at the only part I can't get working:</p>
  
  <pre><code>this.dataSource = Observable.create((observer: any) =&gt; {
      // Runs on every search
      observer.next(this.typeAheadResult);
      }).mergeMap((token: string) =&gt; {  
          return this.httpClient.get&lt;string[]&gt;(`${this.typeAheadUrl}?q=${token}`);              
      });
  </code></pre>
  
  <p>Normally, for a call like this I'd do something like:</p>
  
  <pre><code>this.httpClient.get&lt;string[]&gt;(`${this.typeAheadUrl}?q=${token}`)
      .subscribe(results =&gt; this.results = results)
  </code></pre>
  
  <p>But this isn't quite correct</p>