Can't bind to 'typeahead' since it isn't a known property of 'input'

occasl picture occasl · Nov 15, 2016 · Viewed 9.9k times · Source

I'm using Angular 2.1.2 and I'm having trouble using ng2-bootstrap's typeahead feature, which I'm using version 1.1.16. I'm also using Webpack. I basically following the example on the website, but I adjusted it to use a service I have which will provide the search results for the typeahead field. Any idea why I'm getting this error? I'm also wondering why it says "elected" in the error message instead of "selected" like I have in the HTML below.

Unhandled Promise rejection: Template parse errors:
Can't bind to 'typeahead' since it isn't a known property of 'input'. ("elected | json}}</pre>
                    <input [(ngModel)]="selected"
                           [ERROR ->][typeahead]="chipFamilies"
                           (typeaheadOnSelect)="typeaheadOnSelect($event)""): AppComponent@76:27 ; Zone: <root> ; Task: Promise.then ; Value: Error: Template parse errors:(…) Error: Template parse errors:
Can't bind to 'typeahead' since it isn't a known property of 'input'. ("elected | json}}</pre>
                    <input [(ngModel)]="selected"
                           [ERROR ->][typeahead]="chipFamilies"
                           (typeaheadOnSelect)="typeaheadOnSelect($event)""): AppComponent@76:27
    at TemplateParser.parse (eval at <anonymous> (http://localhost:3000/vendor.js:94:2), <anonymous>:7711:21)
    at RuntimeCompiler._compileTemplate (eval at <anonymous> (http://localhost:3000/vendor.js:94:2), <anonymous>:17193:53)
    at eval (eval at <anonymous> (http://localhost:3000/vendor.js:94:2), <anonymous>:17098:85)
    at Set.forEach (native)
    at compile (eval at <anonymous> (http://localhost:3000/vendor.js:94:2), <anonymous>:17098:49)
    at ZoneDelegate.invoke (eval at <anonymous> (http://localhost:3000/polyfills.js:2294:2), <anonymous>:232:26)
    at Zone.run (eval at <anonymous> (http://localhost:3000/polyfills.js:2294:2), <anonymous>:114:43)
    at eval (eval at <anonymous> (http://localhost:3000/polyfills.js:2294:2), <anonymous>:502:57)
    at ZoneDelegate.invokeTask (eval at <anonymous> (http://localhost:3000/polyfills.js:2294:2), <anonymous>:265:35)
    at Zone.runTask (eval at <anonymous> (http://localhost:3000/polyfills.js:2294:2), <anonymous>:154:47)
    at drainMicroTaskQueue (eval at <anonymous> (http://localhost:3000/polyfills.js:2294:2), <anonymous>:401:35) 

HTML:

     <form class="navbar-form navbar-right" role="search">
            <div class="form-group">
                <pre class="card card-block card-header">Model: {{selected | json}}</pre>
                <input [(ngModel)]="selected"
                       [typeahead]="chipFamilies"
                       (typeaheadOnSelect)="typeaheadOnSelect($event)"
                       class="form-control" style="width: 250px;" placeholder="Search Chip Families">

            </div>
        </form>

TypeScript:

import {Component, OnInit} from '@angular/core';

import 'bootstrap/dist/css/bootstrap.css';
import '../css/main.css';

import {ChipFamilyService} from './chip-family/chip-family.service';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

import { TypeaheadMatch } from '../../node_modules/ng2-bootstrap/components/typeahead/typeahead-match.class';

import { IChipFamily } from './chip-family/chip-family';

@Component({
    selector: 'my-app',
    template: require('./app.component.html'),
    providers: [ChipFamilyService]
})

export class AppComponent implements OnInit {
    public typeaheadLoading:boolean = false;
    public typeaheadNoResults:boolean = false;
    public dataSource:Observable<any>;
    public asyncSelected:string = '';
    public selected: string = '';
    chipFamilies: Array<IChipFamily>;
    errorMessage: string;

    public constructor(private _adminService: ChipFamilyService) {
        this.dataSource = Observable.create((observer:any) => {
            // Runs on every search
            observer.next(this.asyncSelected);
        }).mergeMap((token:string) => this.getChipFamiliesAsObservable(token));
    }

    ngOnInit() {
        this._adminService.getChipFamilies().subscribe(
            chipFamilies => this.chipFamilies = chipFamilies,
            error => this.errorMessage = <any>error
        );
        console.log('AppComponent initializing...');
    }

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

        return Observable.of(
            this.chipFamilies.filter((chipFamily:any) => {
                return query.test(chipFamily.name);
            })
        );
    }
    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);
    }
}

Answer

Poul Kruijt picture Poul Kruijt · Nov 15, 2016

You should probably import the TypeaheadModule into your NgModule definition of your app:

import {TypeaheadModule} from 'ng2-bootstrap/components/typeahead';

@NgModule({
    imports : [
        //...
        TypeaheadModule
    ],
    //...
})
export class AppModule {}