All Components

ComboBox Overview

The ComboBox is a form component that allows you to choose from a list of options.

It is a richer version of the <select> element that provides support for entering custom values, data binding, filtering, and templates.

Basic Usage

The following example demonstrates the ComboBox in action.

@Component({
  selector: 'my-app',
  template: `
    <div class="example-config">
      <input id="ac" type="checkbox" [(ngModel)]="allowCustom">
      <label for="ac">Allow custom values</label>
    </div>
    <div class="example-wrapper">
    <p>Favorite sport:</p>
    <kendo-combobox [data]="listItems" [allowCustom]="allowCustom">
    </kendo-combobox>
    </div>
  `
})
class AppComponent {
    public allowCustom: boolean = true;
    public listItems: Array<string> = ["Baseball", "Basketball", "Cricket", "Field Hockey", "Football", "Table Tennis", "Tennis", "Volleyball"];
}

Configuration

Data Binding

The ComboBox enables you to bind data of the primitive (strings and numbers) or of the complex (objects) type.

It also supports binding to an asynchronous source.

Bind to Arrays of Primitive Data

The following example demonstrates how to bind the ComboBox to an array of primitive data.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox [data]="listItems"></kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<string> = ["X-Small", "Small", "Medium", "Large", "X-Large", "2X-Large"];
}

Bind to Arrays of Complex Data

When the component is bound to complex data (objects), define the textField and valueField properties. The ComboBox will extract the value and text values from the selected data item and in this way will set the selected value and text.

The following example demonstrates how to bind the ComboBox to an array of objects.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="listItems"
        [textField]="'text'"
        [valueField]="'value'"
    >
    </kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];
}

Bind to Remote Data

The following example demonstrates how to bind the ComboBox to remote data by using a service.

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

import { DataService } from './data.service';

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox [data]="listItems"
      [textField]="'ProductName'"
      [valueField]="'ProductId'"
      [placeholder]="'Select Product...'" >
    </kendo-combobox>
  `,
  providers:[DataService]
})

export class AppComponent {

    public listItems: Array<string> = [];

    constructor (private dataService: DataService) { }

    ngOnInit() {
      this.dataService.fetchData().subscribe(
      (data) => this.listItems = data
      )
    }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule, JsonpModule } from '@angular/http';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';

import { AppComponent }   from './app.component';

@NgModule({
  imports: [
    BrowserModule,
    HttpModule,
    JsonpModule,
    DropDownsModule
  ],
  declarations: [
    AppComponent
  ],
  bootstrap: [
    AppComponent
  ]
})
export class AppModule { }
import { AppModule } from './ng.module';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
import { Injectable } from '@angular/core';
import { Jsonp, JsonpModule } from '@angular/http';

@Injectable()

export class DataService {


  constructor( private jsonp: Jsonp) { }

  fetchData(action: string = "", data?: Product): Observable<Product[]>{
    return this.jsonp.get(`http://demos.telerik.com/kendo-ui/service/Products/${action}?callback=JSONP_CALLBACK${this.serializeModels(data)}`).map(response => response.json())
  }

  private serializeModels(data?: Product): string {
    return data ? `&models=${JSON.stringify([data])}` : '';
  }

}
export class Product {
    constructor(
        public ProductID?: number,
        public ProductName?: string,
    ) { }
}

Bind to Remote Data by Using the Async Pipe

The following example demonstrates how to bind the ComboBox to an asynchronous source.

import { Component } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { CategoriesService } from './categories.service';

@Component({
  providers: [CategoriesService],
  selector: 'my-app',
  template: `
      <kendo-combobox
          [data]="view | async"
          [textField]="'CategoryName'"
          [valueField]="'CategoryID'"
        >
      </kendo-combobox>
  `
})
export class AppComponent {
    constructor(private service: CategoriesService) {
        this.view = service;

        this.service.query();
    }

    private view: Observable<any>;
}
import { Injectable } from '@angular/core';
import { Http, HttpModule } from '@angular/http';

import { BehaviorSubject } from 'rxjs/Rx';

@Injectable()
export class CategoriesService extends BehaviorSubject<any> {
    constructor(private http: Http) {
        super(null);
    }

    public query(): void {
        this.fetch(this.tableName)
            .subscribe(x => super.next(x));
    }

    private BASE_URL: string = 'http://services.odata.org/V4/Northwind/Northwind.svc/';
    private tableName: string = "Categories";

    private fetch(tableName: string): any {
        const queryStr = `$skip=0&$count=true`;
        return this.http
            .get(`${this.BASE_URL}${tableName}?${queryStr}`)
            .map(response => response.json().value);
    }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule, JsonpModule } from '@angular/http';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';

import { AppComponent }   from './app.component';

@NgModule({
  imports: [
    BrowserModule,
    HttpModule,
    JsonpModule,
    DropDownsModule
  ],
  declarations: [
    AppComponent
  ],
  bootstrap: [
    AppComponent
  ]
})
export class AppModule { }
import { AppModule } from './ng.module';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

Stream Data by Using the Async Pipe

The ComboBox provides an option to bind it to asynchronous data (observables) by using the async pipe.

The following example demonstrates how to apply this behavior. It starts with an empty observable, produces one random value each second, and emits values in batches of five.

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/interval';
import 'rxjs/add/operator/bufferCount';

@Component({
  selector: 'my-app',
  template: `
    <p>The selected value will disappear when the new data is set.</p>
    <p>A new data will be available every 5 seconds (initially the ComboBox will be empty).</p>
    <kendo-combobox [data]="listItems | async"></kendo-combobox>
  `
})
export class AppComponent {
  public listItems: Observable<string[]>;

  constructor() {
    this.listItems = Observable.interval(1000).map((x) =>  "New item " + x).bufferCount(5);
  }
}

Templates

To customize the list item, selected value, the popup footer or header content, use the item, value, footer, and header templates.

Item Template

Use the item template to customize the content of every list item. To define an item template, nest a <template> tag with an kendoComboBoxItemTemplate directive inside <kendo-combobox>.

The template context is set to the current ComboBox component. To get a reference to the current data item, use the let-dataItem directive.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="listItems"
        [textField]="'text'"
        [valueField]="'value'"
        [value]="selectedValue"
        [valuePrimitive]="true"
    >
        <template kendoComboBoxItemTemplate let-dataItem>
            {{ dataItem.text }} | {{ dataItem.value }}
        </template>
    </kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];

    public selectedValue: number = 2;
}

Header Template

Use the header template to customize the popup header element. To define a header template, nest a <template> tag with a kendoComboBoxHeaderTemplate directive inside <kendo-combobox>.

The template context is set to the current ComboBox component.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="listItems"
        [textField]="'text'"
        [valueField]="'value'"
        [value]="selectedValue"
        [valuePrimitive]="true"
    >
        <template kendoComboBoxHeaderTemplate>
            <h4>Header template</h4>
        </template>
    </kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];

    public selectedValue: number = 2;
}

Use the footer template to customize the popup footer element. To define a footer template, nest a <template> tag with a kendoComboBoxFooterTemplate directive inside <kendo-combobox>.

The template context is set to the current ComboBox component.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="listItems"
        [textField]="'text'"
        [valueField]="'value'"
        [value]="selectedValue"
        [valuePrimitive]="true"
    >
        <template kendoComboBoxFooterTemplate>
            <h4>Footer template</h4>
        </template>
    </kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];

    public selectedValue: number = 2;
}

No-Data Template

Use the no-data template to customize the popup content when no data is present. To define a no-data template, nest a <template> tag with a kendoComboBoxNoDataTemplate directive inside <kendo-combobox>.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="listItems"
    >
        <template kendoDropDownListNoDataTemplate>
            <h4>No data here!</h4>
        </template>
    </kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<{ text: string, value: number }> = [];
}

Value Selection

The ComboBox allows for defining its selected value as primitive (strings, numbers) or complex (objects). It depends on the valuePrimitive configuration option when to use which.

Specify the Value Type

To specify the value type, set the valuePrimitive property. By default, it is set to false—the value has to match the data type. If the valuePrimitive property is set to true, the value has to be of the primitive type.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="listItems"
        [textField]="'text'"
        [valueField]="'value'"
        [value]="selectedObject"
    >
    </kendo-combobox>
    <kendo-combobox
        [data]="listItems"
        [textField]="'text'"
        [valueField]="'value'"
        [value]="selectedPrimitive"
        [valuePrimitive]="true"
    >
    </kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];

    public selectedObject: { text: string, value: number } = { text: "Medium", value: 2 };
    public selectedPrimitive: number = 2;
}

Set the Value Property Binding

It is possible to set the value of the ComboBox through its [value] property binding. The component accepts values of the complex (objects) or the primitive (strings or numbers) type. To specify the value type, set the valuePrimitive property. By default, it is set to false—the value has to match the data type. When the value changes, the ComboBox triggers the valueChange event.

The following example demonstrates how to select an item by using primitive values.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="listItems"
        [textField]="'text'"
        [valueField]="'value'"
        [value]="selectedValue"
        [valuePrimitive]="true"
    >
    </kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];

    public selectedValue: number = 2;
}

The following example demonstrates how to select an item by using complex values.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="listItems"
        [textField]="'text'"
        [valueField]="'value'"
        [value]="selectedValue"
    >
    </kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];

    public selectedValue: { text: string, value: number } = { text: "Medium", value: 2 };
}

Forms Support

It is possible to use the ComboBox in template-driven or reactive forms. The component accepts values of the complex (objects) or the primitive (strings or numbers) type. To specify the value type, set the valuePrimitive property. By default, it is set to false—the value has to match the data type.

Template-Driven Forms

The template-driven forms enable you to bind the ComboBox to the model by using the ngModel directive.

The following example demonstrates how to accomplish a two-way data binding by using the ngModel directive. The model field is a complex value.

@Component({
  selector: 'my-app',
  template: `
    <form #form="ngForm">
        <fieldset>
            The Selected gender is <pre>{{ gender | json }}</pre>
        </fieldset>
        <fieldset>
            <label>
                Select Gender:
                <kendo-combobox
                    name="gender"
                    [data]="genders"
                    [textField]="'text'"
                    [valueField]="'value'"
                    [(ngModel)]="gender"
                >
                </kendo-combobox>
            </label>
        </fieldset>
    </form>
  `
})
class AppComponent {
    public genders: Array<{ text: string, value: number }> = [
        { text: "Male", value: 1 },
        { text: "Female", value: 2 }
    ];

    public gender: { text: string, value: number } = { text: "Female", value: 2 };
}

The following example demonstrates how to accomplish a two-way data binding by using the ngModel directive. The model field is a primitive value.

@Component({
  selector: 'my-app',
  template: `
    <form #form="ngForm">
        <fieldset>
            The Selected gender is <pre>{{ gender | json }}</pre>
        </fieldset>
        <fieldset>
            <label>
                Select Gender:
                <kendo-combobox
                    name="gender"
                    [data]="genders"
                    [textField]="'text'"
                    [valueField]="'value'"
                    [valuePrimitive]="true"
                    [(ngModel)]="gender"
                >
                </kendo-combobox>
            </label>
        </fieldset>
    </form>
  `
})
class AppComponent {
    public genders: Array<{ text: string, value: number }> = [
        { text: "Male", value: 1 },
        { text: "Female", value: 2 }
    ];

    public gender: { text: string, value: number } = 2;
}

Reactive Forms

The FormGroup provides a way to render reactive forms. For more details, refer to the Angular Documentation.

The following example demonstrates how to use the ComboBox in a reactive form with a primitive value binding.

import {
    FormsModule,
    ReactiveFormsModule,
    FormGroup,
    FormControl
} from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
    <form [formGroup]="myForm">
        <fieldset>
        The form.gender value is: {{myForm.controls.gender.value}}
        <br />
        The form is valid: {{myForm.controls.gender.valid}}
        </fieldset>
        <label>
            Select gender
            <kendo-combobox
                formControlName="gender"
                [data]="genders"
                [textField]="'text'"
                [valueField]="'value'"
                [valuePrimitive]="true"
                required
            >
            </kendo-combobox>
        </label>
    </form>
  `
})
class AppComponent {
    public genders: Array<{ text: string, value: number }> = [
        { text: "Male", value: 1 },
        { text: "Female", value: 2 }
    ];

    public myForm: FormGroup = new FormGroup({
        gender: new FormControl(2)
    });
}

The following example demonstrates how to use the ComboBox in a reactive form with a complex value binding.

import {
    FormsModule,
    ReactiveFormsModule,
    FormGroup,
    FormControl
} from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
    <form [formGroup]="myForm">
        <fieldset>
        The form.gender value is: <pre>{{myForm.controls.gender.value | json}}</pre>
        <br />
        The form is valid: {{myForm.controls.gender.valid}}
        </fieldset>
        <label>
            Select gender
            <kendo-combobox
                formControlName="gender"
                [data]="genders"
                [textField]="'text'"
                [valueField]="'value'"
                required
            >
            </kendo-combobox>
        </label>
    </form>
  `
})
class AppComponent {
    public genders: Array<{ text: string, value: number }> = [
        { text: "Male", value: 1 },
        { text: "Female", value: 2 }
    ];

    public myForm: FormGroup = new FormGroup({
        gender: new FormControl({ text: "Female", value: 2 })
    });
}

Filtering

To turn on filtering, set the filterable property to true. Whenever the user modifies the input value, the ComboBox triggers a filterChange event.

The event argument contains the typed string value that you can use to filter the source.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="data"
        [textField]="'text'"
        [valueField]="'value'"
        [filterable]="true"
        (filterChange)="handleFilter($event)"
    >
    </kendo-combobox>
  `
})
class AppComponent {
    public source: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];

    public data: Array<{ text: string, value: number }>;

    constructor() {
        this.data = this.source.slice();
    }

    handleFilter(value) {
        this.data = this.source.filter((s) => s.text.toLowerCase().indexOf(value.toLowerCase()) !== -1);
    }
}

Suggestion

To turn on suggestions set suggest property to true. Whenever the user modifies the input value, the ComboBox will autocomplete the user input with the first text match. If the first text match does not begin with the current user input, no suggestion will be displayed.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox [data]="listItems" [suggest]="true"></kendo-combobox>
  `
})
class AppComponent {
    public listItems: Array<string> = ["Item 1", "Item 2", "Item 3", "Item 4"];
}

Events

On Change of Item Selection

The selectionChange event is triggered when the item selection is changed.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="data"
        [textField]="'text'"
        [valueField]="'value'"
        (selectionChange)="handleSelection($event)"
    >
    </kendo-combobox>
    <br />

    Last 10 calls:
    <ul>
        <li *ngFor="let call of eventCalls">{{ call.name }}: <pre>{{ call.value | json }}</pre></li>
    </ul>
  `
})
class AppComponent {
    public data: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];

    public eventCalls: Array<any> = [];

    last10Calls() {
        const end = this.eventCalls.length;

        return this.eventCalls.slice(Math.max(0, end - 10), end);
    }

    handleSelection(value) {
        this.eventCalls = this.last10Calls().concat([ { name: 'select', value: value } ]);
    }
}

On Value Change

The valueChange event is triggered when the selected value is changed. If the popup is open, the valueChange event will not fire. To raise the change event when the popup is still opened, either blur the component or press ENTER.

@Component({
  selector: 'my-app',
  template: `
    <kendo-combobox
        [data]="data"
        [textField]="'text'"
        [valueField]="'value'"
        (valueChange)="handleValue($event)"
    >
    </kendo-combobox>
    <br />

    Last 10 calls:
    <ul>
        <li *ngFor="let call of eventCalls">{{ call.name }}: <pre>{{ call.value | json }}</pre></li>
    </ul>
  `
})
class AppComponent {
    public data: Array<{ text: string, value: number }> = [
        { text: "Small", value: 1 },
        { text: "Medium", value: 2 },
        { text: "Large", value: 3 }
    ];

    public eventCalls: Array<any> = [];

    last10Calls() {
        const end = this.eventCalls.length;

        return this.eventCalls.slice(Math.max(0, end - 10), end);
    }

    handleValue(value) {
        this.eventCalls = this.last10Calls().concat([ { name: 'change', value: value } ]);
    }
}

On Filter Change

The filterChange event fires when the user types inside the filter input. For more details, refer to the section on filtering.

In this article