Dynamic Country and State Dropdowns in Angular using Web API
Dynamic Country and State Dropdowns in Angular using Web API
When building modern web applications, especially employee forms
or address inputs, it's common to let users select their country and state from
a dynamic list. Instead of hardcoding these options, we’ll make them dynamic by
fetching them from a backend API.
In this tutorial, we’ll walk through how to create an employee
form in Angular that:
- Loads
countries from a backend API on initialization.
- Loads states
based on the selected country.
- Submits the
complete form data.
Backend API Structure
For this example, we'll assume an ASP.NET Web API with the
following endpoints:
GET
/api/countries // Returns
a list of countries
GET /api/states?countryId=1 // Returns states for a
specific country
Each country/state might look like:
// Country
{ "id": 1, "name": "United States" }
// State
{ "id": 101, "name": "California",
"countryId": 1 }
Step 1: Angular Setup
Ensure HttpClientModule is imported in your Angular app module:
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [HttpClientModule]
})
export class AppModule {}
Step 2: Creating the Country Service
We’ll create a service to communicate with our API.
// country.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class CountryService {
private apiUrl = 'https://yourapi.com/api';
constructor(private http: HttpClient) {}
getCountries(): Observable<any[]> {
return
this.http.get<any[]>(`${this.apiUrl}/countries`);
}
getStatesByCountryId(countryId: number):
Observable<any[]> {
return
this.http.get<any[]>(`${this.apiUrl}/states?countryId=${countryId}`);
}
}
Step 3: Building the Employee Form Component
Here’s how we use FormBuilder to create the reactive form and bind
it to dynamic data:
// employee-form.component.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { CountryService } from '../services/country.service';
@Component({
selector: 'app-employee-form',
templateUrl: './employee-form.component.html'
})
export class EmployeeFormComponent implements OnInit {
form: FormGroup;
countries: any[] = [];
states: any[] = [];
constructor(private fb: FormBuilder, private
countryService: CountryService) {
this.form = this.fb.group({
name: [''],
country: [''],
state: ['']
});
}
ngOnInit() {
this.countryService.getCountries().subscribe(data
=> {
this.countries = data;
});
this.form.get('country')?.valueChanges.subscribe(countryId
=> {
if (countryId) {
this.countryService.getStatesByCountryId(countryId).subscribe(states
=> {
this.states
= states;
this.form.get('state')?.setValue('');
});
} else {
this.states = [];
this.form.get('state')?.setValue('');
}
});
}
onSubmit() {
console.log('Form submitted:',
this.form.value);
}
}
Step 4: Template for the Employee Form
Here's the HTML form using Angular’s reactive form binding:
<!-- employee-form.component.html -->
<form [formGroup]="form"
(ngSubmit)="onSubmit()">
<label>Name:</label>
<input formControlName="name"
type="text" />
<label>Country:</label>
<select formControlName="country">
<option value="">Select
Country</option>
<option *ngFor="let country of
countries" [value]="country.id">
{{ country.name }}
</option>
</select>
<label>State:</label>
<select formControlName="state"
[disabled]="!states.length">
<option value="">Select
State</option>
<option *ngFor="let state of
states" [value]="state.id">
{{ state.name }}
</option>
</select>
<button
type="submit">Submit</button>
</form>
Result
When a user selects a country:
- The list of
states is automatically updated.
- The form
updates dynamically and remains reactive.
- The selected
values are logged or submitted as needed.
Final Tips
- Always
handle errors from API calls using catchError() in production apps.
- Use type
interfaces (Country, State) to strongly type your API data.
- Consider
caching countries if they rarely change to reduce backend calls.
Conclusion
You now have a fully dynamic, reactive form in Angular that
populates country and state fields from a backend API. This is a common pattern
in real-world applications, and mastering it helps you create flexible,
scalable forms.
Comments
Post a Comment