Forms Support

You can use the DropDownList 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—just like the defaultItem, the value has to match the data type.

Template-Driven Forms

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

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

@Component({
  selector: 'my-app',
  template: `
    <div class="example-config">
        The selected gender is <strong>{{ gender | json }}</strong>
    </div>
    <div class="example-wrapper">
        <form #form="ngForm">
                <kendo-label [for]="genderList" [text]="'Select Gender'"></kendo-label>
                <kendo-dropdownlist
                    #genderList
                    name="gender"
                    [data]="genders"
                    [textField]="'text'"
                    [valueField]="'value'"
                    [(ngModel)]="gender"
                >
                </kendo-dropdownlist>
        </form>
    </div>
  `
})
class AppComponent {
    public genders: Array<{ text: string, value: number }> = [
        { text: 'Male', value: 1 },
        { text: 'Female', value: 2 },
        { text: 'Other', value: 3 }
    ];

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

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

@Component({
  selector: 'my-app',
  template: `
    <div class="example-config">
        The selected gender is <strong>{{ gender | json }}</strong>
    </div>
    <form #form="ngForm">
        <kendo-label [for]="genderList" [text]="'Select Gender'"></kendo-label>
        <kendo-dropdownlist
            #genderList
            name="gender"
            [data]="genders"
            [textField]="'text'"
            [valueField]="'value'"
            [valuePrimitive]="true"
            [(ngModel)]="gender"
        >
        </kendo-dropdownlist>
    </form>
  `
})
class AppComponent {
    public genders: Array<{ text: string, value: number }> = [
        { text: 'Male', value: 1 },
        { text: 'Female', value: 2 },
        { text: 'Other', value: 3 }
    ];

    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 DropDownList in a reactive form with a primitive value binding.
 

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

@Component({
  selector: 'my-app',
  template: `
    <div class="example-config">
        <p>The form is valid: <strong>{{ myForm.controls.gender.valid }}</strong></p>
        <p>The form.gender value is: <strong>{{ myForm.controls.gender.value }}</strong></p>
    </div>
    <form [formGroup]="myForm">
        <kendo-label [for]="gender" [text]="'Select Gender'"></kendo-label>
        <kendo-dropdownlist
            #gender
            formControlName="gender"
            [data]="genders"
            [defaultItem]="{ text: 'Select gender', value: null }"
            [textField]="'text'"
            [valueField]="'value'"
            [valuePrimitive]="true"
            required
        >
        </kendo-dropdownlist>
    </form>
  `
})
class AppComponent {
    public genders: Array<{ text: string, value: number }> = [
        { text: 'Male', value: 1 },
        { text: 'Female', value: 2 }
    ];

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

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

The following example demonstrates how to use the DropDownList in a reactive form with a complex value binding and required validation.

import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { requiredValidatorLogic } from './required.directive';

@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>
        <kendo-label [for]="gender" [text]="'Select Gender'"></kendo-label>
        <kendo-dropdownlist
            #gender
            isRequired="true"
            formControlName="gender"
            [data]="genders"
            [defaultItem]="{ text: 'Select gender', value: null }"
            [textField]="'text'"
            [valueField]="'id'"
        >
        </kendo-dropdownlist>
    </form>
  `
})

export class AppComponent {
    public genders: Array<{ text: string, id: number }> = [
        { text: 'Male', id: 1 },
        { text: 'Female', id: 2 }
    ];

    public myForm: FormGroup = new FormGroup({
        gender: new FormControl({}, requiredValidatorLogic)
    });
}
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
import { AppComponent } from './app.component';
import { RequiredValidator } from './required.directive';

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
    declarations: [ AppComponent, RequiredValidator ],
    imports: [ BrowserModule, BrowserAnimationsModule, FormsModule, ReactiveFormsModule, DropDownsModule ],
    bootstrap: [ AppComponent ]
})

export class AppModule { }
import {
    forwardRef,
    Directive,
    Attribute
} from '@angular/core';

import {
    Validator,
    NG_VALIDATORS
} from '@angular/forms';

export const requiredValidatorLogic = (required) => (control) => {
    if (!control.value) {
        return { valid: false };
    }

    return control.value.id && control.value.id !== null ?
        null : { valid: false };
};

const Required_VALIDATOR: any = {
   provide: NG_VALIDATORS,
   // tslint:disable-next-line:no-use-before-declare
   useExisting: forwardRef(() => RequiredValidator),
   multi: true
};

@Directive({
     selector: '[isRequired]',
     providers: [Required_VALIDATOR]
})
export class RequiredValidator implements Validator {
    private _validator: any;
    constructor(@Attribute('isRequired') required: boolean) {
        this._validator = requiredValidatorLogic(required);
    }
    validate(c) {
        return this._validator(c);
    }
}

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

enableProdMode();

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

The required built-in validator does not support object validation. If a defaultItem is set, the developer needs to implement the required custom validation, as demonstrated in the example.

FormField Association

The following example demonstrates the usage of the DropDownList within a FormField with hint and error messages.

import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
    selector: 'my-app',
    template: `
        <div class="example">
            <form class="k-form" [formGroup]="form">
                <kendo-formfield>
                    <kendo-label [for]="size" text="Size"></kendo-label>
                    <kendo-dropdownlist
                        #size
                        [formControlName]="'size'"
                        [data]="sizes"
                    >
                    </kendo-dropdownlist>
                    <kendo-formhint>European sizes standard</kendo-formhint>
                    <kendo-formerror>Required</kendo-formerror>
                </kendo-formfield>
            </form>
        </div>
    `,
    styles: [`
        .example {
            display: flex;
            justify-content: center;
        }
        .k-form {
            width: 400px;
        }
    `]
})
export class AppComponent {
    public form: FormGroup = new FormGroup({
        size: new FormControl(null, Validators.required)
    });

    public sizes: string[] = ['X-Small', 'Small', 'Medium', 'Large', 'X-Large', '2X-Large'];
}
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
import { LabelModule } from '@progress/kendo-angular-label';
import { InputsModule } from '@progress/kendo-angular-inputs';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
    declarations: [AppComponent],
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        FormsModule,
        ReactiveFormsModule,
        DropDownsModule,
        LabelModule,
        InputsModule
    ],
    bootstrap: [AppComponent]
})

export class AppModule { }
import { AppModule } from './app.module';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

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

In this article