How to work with SELECT-OPTIONS form control in Angular

SELECT-OPTIONS form control is used very often in any form of any website. For example selecting country when you register an account on Google site.

<select>	
    <option value="us">United States</option>
    <option value="uk">United Kingdom</option>
    <option value="ca">Canada</option>
</select>

So how to implement it in Angular form, in Angular we have Template-driven forms and Reactive forms. We will start with Template-driven forms first.

Data

For example we have a list of countries which can be static in code or can be retrieved from an API.

const countries = [
	{
		id: 'us',
		name: 'United States'
	},
	{
		id: 'uk',
		name: 'United Kingdom'
	},
	{
		id: 'ca',
		name: 'Canada'
	}
];

Template-driven Forms

If you want to tracks simple string values bound to the option element, we can use [value] property in option.
<form #f="ngForm">
    <select name="country" ngModel>
        <option value="" disabled>Choose your country</option>
        <option *ngFor="let country of countries" [value]="country.id">
            {{ country.name }}
        </option>
    </select>
</form>

If you select United States, the form value should look like this:

{country: 'us'}
If you want to tracks object values bound to the option element, we can use [ngValue] property in option.
<form #f="ngForm">
    <select name="country" ngModel>
        <option value="" disabled>Choose your country</option>
        <option *ngFor="let country of countries" [ngValue]="country">
            {{ country.name }}
        </option>
    </select>
</form>

If you select United States, the form value should look like this:

{country: {'id': 'us', 'name': 'United States'}}

But when you want to display the selected country in the <select> that you selected before with object tracking option, you need to do one more step to achieve it. We need to use compareWith directive which helps us compare field in an object.

<form #f="ngForm">
    <select [compareWith]="compareFn" name="country" ngModel>
        <option value="" disabled>Choose your country</option>
        <option *ngFor="let country of countries" [ngValue]="country">
            {{ country.name }}
        </option>
    </select>
</form>
compareFn(c1: Country, c2: Country): boolean {
    return c1 && c2 ? c1.id === c2.id : c1 === c2;
}

Let's see how it work on stackblitz:

Reactive Forms

The concept of implementing <select> is similar to above. We also have two cases that we can track simple string or object with using [value] or [ngValue] .

The different is in Reactive forms we will define form controls in ts code instead of from template.

Tracking simple string

<form [formGroup]="form">
    <select formControlName="country">
        <option *ngFor="let country of countries" [value]="country.id">
            {{ country.name }}
        </option>
    </select>
</form>
form = new FormGroup({
    country: new FormControl('us')
});

Tracking object

<form [formGroup]="form">
    <select [compareWith]="compareFn" formControlName="country">
        <option *ngFor="let country of countries" [ngValue]="country">
            {{ country.name }}
        </option>
    </select>
</form>
form = new FormGroup({
    country: new FormControl({id: 'uk', name: 'United Kingdom'})
});

compareFn(c1: Country, c2: Country): boolean {
    return c1 && c2 ? c1.id === c2.id : c1 === c2;
}

With tracking object, don't forget to use [compareWith] directive to show the selected value in the select at the first time.

Let's check it on stackblitz:

I hope after reading this post you're able to use select-option in Angular proper way and you will not be confuse by [value] and [ngValue] anymore.

Have fun!

Show Comments

Get the latest posts delivered right to your inbox.