For the Angular Select Dropdown example, let's begin with creating a component for dropdown.
This example is compatible with Angular 8, 9.
Create a DropdownComponent component using the command,
ng g c dropdown
This will create a dropdown folder under the app folder. The app\dropdown folder will contain the generated files.
Basic Dropdown using Reactive forms
First, we see a basic dropdown using Reactive forms.
Typescript file
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'app-dropdown',
templateUrl: './dropdown.component.html',
styleUrls: ['./dropdown.component.css']
})
export class DropdownComponent implements OnInit {
form: FormGroup;
categories: any = [
{ itemId: 1, item: "Clothing" },
{ itemId: 2, item: "Mobiles" },
{ itemId: 3, item: "Watches" },
{ itemId: 4, item: "Electronics" },
{ itemId: 5, item: "Sports" },
{ itemId: 6, item: "Fashion" },
{ itemId: 7, item: "Furniture" }
];
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.form = this.fb.group({
category: [null]
});
}
categoryOnChange(e) {
console.log(e.target.value);
}
submit() {
console.log("Selected Category :" + JSON.stringify(this.form.value))
}
}
HTML
<form [formGroup]="form" (ngSubmit)="submit()">
<div>
<label>Category</label>
<div>
<select formControlName="category" (change)="categoryOnChange($event)">
<option [ngValue]="Select" disabled selected value>Select</option>
<option *ngFor="let category of categories;" [ngValue]="category.item">
{{category.item}}
</option>
</select>
<button type="submit">Submit</button>
</div>
</div>
</form>
In the above simple dropdown, the option is populated using a categories array. Here the array values are hardcoded. In real time array values may be hardcoded or will come from service response.
The form value is displayed in the console using submit and (change) event. On select option change, the categoryOnChange($event) method will be called.
Dropdown with Validation
The Dropdown can be validated with Validators.
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
ngOnInit() {
this.form = this.fb.group({
category: ['', [Validators.required]]
});
}
get f(){
return this.form.controls;
}
To include validation, In the TypeScript component include these changes.
In HTML include the below change below the select element. Add a disabled property in the button. Only when the form is valid the button will be enabled.
<form>
<div>
<select formControlName="category" (change)="categoryOnChange($event)">
</select>
<div *ngIf="f.category.touched && f.category.invalid" class="alert alert-danger">
<div *ngIf="f.category.errors.required">Select any Category.</div>
</div>
<button [disabled]="!form.valid" type="submit">Submit</button>
</div>
</form>
If you click the option and without selecting any option you will see the validation error message onBlur.
Dropdown using Observables
So far we saw a dropdown option with a change event. We can also get the dropdown valueChanges. valueChanges property is an Observable. You need to Subscribe to the valueChanges Observable to print the value in console and HTML.
A code snippet is shown for typescript and template changes.
ngOnInit() {
this.form.get("category").valueChanges
.subscribe(category => {
this.categoryOnChangeSubscription(category);
})
}
categoryOnChangeSubscription(category) {
this.selectedCategory = category;
console.log("Subscribed Category ValueChange:");
console.log(category);
}
categoryOnChangeSubscription function assigns the value to the selectedCategory property to display in UI and console log prints the subscribed value change.
<div *ngIf="submitted">Selected Category is {{selectedCategory}}</div>
Final Code
dropdown.component.ts
import { Component, OnInit, VERSION } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-dropdown',
templateUrl: './dropdown.component.html',
styleUrls: ['./dropdown.component.css']
})
export class DropdownComponent implements OnInit {
form: FormGroup;
version: string;
selectedCategory: string;
submitted:boolean = false;
categories: any = [
{ itemId: 1, item: "Clothing" },
{ itemId: 2, item: "Mobiles" },
{ itemId: 3, item: "Watches" },
{ itemId: 4, item: "Electronics" },
{ itemId: 5, item: "Sports" },
{ itemId: 6, item: "Fashion" },
{ itemId: 7, item: "Furniture" }
];
constructor(private fb: FormBuilder) {
this.version = `Angular! v${VERSION.full}`
}
ngOnInit() {
this.form = this.fb.group({
category: ['', [Validators.required]]
});
this.form.get("category").valueChanges
.subscribe(category => {
this.categoryOnChangeSubscription(category);
})
}
get f() {
return this.form.controls;
}
categoryOnChange(e) {
console.log("Changed Category :");
console.log(e.target.value);
}
categoryOnChangeSubscription(category) {
this.selectedCategory = category;
console.log("Subscribed Category ValueChange:");
console.log(category);
}
submit() {
console.log("Submitted Category :" +
JSON.stringify(this.form.value));
console.log(this.version);
this.submitted = true;
}
}
dropdown.component.html
<form [formGroup]="form" (ngSubmit)="submit()">
<div>
<label>Category</label>
<div>
<select formControlName="category" (change)="categoryOnChange($event)">
<option [ngValue]="Select" disabled selected value>Select</option>
<option *ngFor="let category of categories;" [ngValue]="category.item">
{{category.item}}
</option>
</select>
<div *ngIf="f.category.touched && f.category.invalid" class="alert alert-danger">
<div *ngIf="f.category.errors.required">Select any Category.</div>
</div>
<button [disabled]="!form.valid" type="submit">Submit</button>
</div>
</div>
<div *ngIf="submitted">Selected Category is {{selectedCategory}}</div>
</form>
When you run the application you can see both the console logs in the browser inspect mode as well as the interpolation {{selectedCategory}} value in UI.