Ngx-bootstrap: typeahead styling and arrow up/down problems

Created on 4 Apr 2016  路  2Comments  路  Source: valor-software/ngx-bootstrap

First I thought it was me, but eventually I used the typeahead example from the site on the angular2-quickstart (https://github.com/valor-software/angular2-quickstart). I even tried both the bootstrap 3 and bootstrap 4 just to be sure.

Everything seems to work, except:

  • the styling is different than the example. Somehow it's really hard to debug with chrome inspect where the styles are coming from. I can't find a way to open the typeahead and then inspect the that pops up, because it gets removed as soon as i click anywhere else.
  • in the example on http://valor-software.com/ng2-bootstrap/ you can use the up and down arrow keys to select, but pressing up or down does nothing.

Just to include everything, this is the modified app.component.ts from the angular2-quickstart:

import {Component} from 'angular2/core';
import {CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/common';
import {Alert, TYPEAHEAD_DIRECTIVES, DATEPICKER_DIRECTIVES} from 'ng2-bootstrap/ng2-bootstrap';

@Component({
  selector: 'my-app',
  directives: [Alert, DATEPICKER_DIRECTIVES, TYPEAHEAD_DIRECTIVES, CORE_DIRECTIVES, FORM_DIRECTIVES],
  template: `
    <alert type="info">ng2-bootstrap hello world!</alert>
      <pre>Selected date is: <em *ngIf="dt">{{ getDate() | date:'fullDate'}}</em></pre>
      <h4>Inline</h4>
      <div style="display:inline-block; min-height:290px;">
        <datepicker [(ngModel)]="dt" [minDate]="minDate" [showWeeks]="true"></datepicker>
      </div>

<div class='container-fluid'>
    <h4>Static arrays</h4>
    <pre>Model: {{selected | json}}</pre>
    <input [(ngModel)]="selected"
           [typeahead]="statesComplex"
           (typeaheadOnSelect)="typeaheadOnSelect($event)"
           [typeaheadOptionField]="'name'"
           class="form-control">

    <h4>Asynchronous results</h4>
    <pre>Model: {{asyncSelected | json}}</pre>
    <input [(ngModel)]="asyncSelected"
           [typeahead]="getAsyncData(getContext())"
           (typeaheadLoading)="changeTypeaheadLoading($event)"
           (typeaheadNoResults)="changeTypeaheadNoResults($event)"
           (typeaheadOnSelect)="typeaheadOnSelect($event)"
           [typeaheadOptionsLimit]="7"
           placeholder="Locations loaded with timeout"
           class="form-control">
    <div *ngIf="typeaheadLoading===true">
        <i class="glyphicon glyphicon-refresh ng-hide" style=""></i>
    </div>
    <div *ngIf="typeaheadNoResults===true" class="" style="">
        <i class="glyphicon glyphicon-remove"></i> No Results Found
    </div>
</div>
  `,
})
export class AppComponent {
  public dt:Date = new Date();
  private minDate:Date = null;
  private events:Array<any>;
  private tomorrow:Date;
  private afterTomorrow:Date;
  private formats:Array<string> = ['DD-MM-YYYY', 'YYYY/MM/DD', 'DD.MM.YYYY', 'shortDate'];
  private format = this.formats[0];
  private dateOptions:any = {
    formatYear: 'YY',
    startingDay: 1
  };
  private opened:boolean = false;

  public getDate():number {
    return this.dt && this.dt.getTime() || new Date().getTime();
  }

  private selected:string = '';
  private asyncSelected:string = '';
  private typeaheadLoading:boolean = false;
  private typeaheadNoResults:boolean = false;
  private states:Array<string> = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado',
    'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa',
    'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota',
    'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico',
    'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island',
    'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington',
    'West Virginia', 'Wisconsin', 'Wyoming'];
  private statesComplex:Array<any> = [
    {id: 1, name: 'Alabama'}, {id: 2, name: 'Alaska'}, {id: 3, name: 'Arizona'},
    {id: 4, name: 'Arkansas'}, {id: 5, name: 'California'},
    {id: 6, name: 'Colorado'}, {id: 7, name: 'Connecticut'},
    {id: 8, name: 'Delaware'}, {id: 9, name: 'Florida'},
    {id: 10, name: 'Georgia'}, {id: 11, name: 'Hawaii'},
    {id: 12, name: 'Idaho'}, {id: 13, name: 'Illinois'},
    {id: 14, name: 'Indiana'}, {id: 15, name: 'Iowa'},
    {id: 16, name: 'Kansas'}, {id: 17, name: 'Kentucky'},
    {id: 18, name: 'Louisiana'}, {id: 19, name: 'Maine'},
    {id: 21, name: 'Maryland'}, {id: 22, name: 'Massachusetts'},
    {id: 23, name: 'Michigan'}, {id: 24, name: 'Minnesota'},
    {id: 25, name: 'Mississippi'}, {id: 26, name: 'Missouri'},
    {id: 27, name: 'Montana'}, {id: 28, name: 'Nebraska'},
    {id: 29, name: 'Nevada'}, {id: 30, name: 'New Hampshire'},
    {id: 31, name: 'New Jersey'}, {id: 32, name: 'New Mexico'},
    {id: 33, name: 'New York'}, {id: 34, name: 'North Dakota'},
    {id: 35, name: 'North Carolina'}, {id: 36, name: 'Ohio'},
    {id: 37, name: 'Oklahoma'}, {id: 38, name: 'Oregon'},
    {id: 39, name: 'Pennsylvania'}, {id: 40, name: 'Rhode Island'},
    {id: 41, name: 'South Carolina'}, {id: 42, name: 'South Dakota'},
    {id: 43, name: 'Tennessee'}, {id: 44, name: 'Texas'},
    {id: 45, name: 'Utah'}, {id: 46, name: 'Vermont'},
    {id: 47, name: 'Virginia'}, {id: 48, name: 'Washington'},
    {id: 49, name: 'West Virginia'}, {id: 50, name: 'Wisconsin'},
    {id: 51, name: 'Wyoming'}];

  private getContext() {
    return this;
  }

  private _cache:any;
  private _prevContext:any;

  private getAsyncData(context:any):Function {
    if (this._prevContext === context) {
      return this._cache;
    }

    this._prevContext = context;
    let f:Function = function ():Promise<string[]> {
      let p:Promise<string[]> = new Promise((resolve:Function) => {
        setTimeout(() => {
          let query = new RegExp(context.asyncSelected, 'ig');
          return resolve(context.states.filter((state:any) => {
            return query.test(state);
          }));
        }, 200);
      });
      return p;
    };
    this._cache = f;
    return this._cache;
  }

  private changeTypeaheadLoading(e:boolean) {
    this.typeaheadLoading = e;
  }

  private changeTypeaheadNoResults(e:boolean) {
    this.typeaheadNoResults = e;
  }

  private typeaheadOnSelect(e:any) {
    console.log(`Selected value: ${e.item}`);
  }
}

Most helpful comment

I've finally found the problem. Although the documentation reads that ng2-bootstrap plays nice with bootstrap 4-alpha, it does not actually load in the bootstrap 4 themes by default. There's no documentation on this and it's really annoying, but here's the solution:

Put this at the top of your

  <script type="text/javascript">
    // temporary hack for enable bootstrap 4
    window.__theme = 'bs4';
  </script>

All 2 comments

I've finally found the problem. Although the documentation reads that ng2-bootstrap plays nice with bootstrap 4-alpha, it does not actually load in the bootstrap 4 themes by default. There's no documentation on this and it's really annoying, but here's the solution:

Put this at the top of your

  <script type="text/javascript">
    // temporary hack for enable bootstrap 4
    window.__theme = 'bs4';
  </script>

@rbaarsma Thank you so much for sharing the solution. I had the same problem.

Was this page helpful?
0 / 5 - 0 ratings