Nested FormGroups
Nested FormGroups mirror nested object shapes, keeping form structure aligned with your data model.
Creating Nested Groups
this.form = this.fb.group({
firstName: ['', Validators.required],
lastName: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['', Validators.pattern(/^\d{5}$/)],
}),
});
Template with Nested Groups
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<input formControlName="firstName" placeholder="First name">
<input formControlName="lastName" placeholder="Last name">
<input formControlName="email" placeholder="Email">
<div formGroupName="address">
<input formControlName="street" placeholder="Street">
<input formControlName="city" placeholder="City">
<input formControlName="state" placeholder="State">
<input formControlName="zip" placeholder="ZIP">
</div>
<button type="submit">Save</button>
</form>
Accessing Nested Controls
// Get a nested control
const cityControl = this.form.get('address.city');
// Get the nested group
const addressGroup = this.form.get('address') as FormGroup;
// Check nested validity
const isAddressValid = this.form.get('address')?.valid;
setValue vs patchValue with Nested Forms
// setValue — must provide ALL controls including nested
this.form.setValue({
firstName: 'Alice',
lastName: 'Smith',
email: 'alice@example.com',
address: {
street: '123 Main St',
city: 'Springfield',
state: 'IL',
zip: '62701',
},
});
// patchValue — only update specified controls
this.form.patchValue({
email: 'alice@newemail.com',
address: {
city: 'Chicago',
},
});
Mapping API DTOs to Form Models
Mapping between API DTOs and form models keeps transport concerns out of template code.
API DTO Interface
interface UserDto {
id: number;
firstName: string;
lastName: string;
email: string;
address: {
street: string;
city: string;
state: string;
zip: string;
};
preferences: {
newsletter: boolean;
theme: 'light' | 'dark';
};
}
Loading API Data into the Form
loadUser(id: number): void {
this.userService.getUser(id).subscribe(user => {
this.form.patchValue({
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
address: {
street: user.address.street,
city: user.address.city,
state: user.address.state,
zip: user.address.zip,
},
preferences: {
newsletter: user.preferences.newsletter,
theme: user.preferences.theme,
},
});
});
}
Submitting Form Data to API
onSubmit(): void {
if (!this.form.valid) {
this.form.markAllAsTouched();
return;
}
const formValue = this.form.value;
const userDto: UserDto = {
id: this.userId,
firstName: formValue.firstName,
lastName: formValue.lastName,
email: formValue.email,
address: {
street: formValue.address.street,
city: formValue.address.city,
state: formValue.address.state,
zip: formValue.address.zip,
},
preferences: {
newsletter: formValue.preferences.newsletter,
theme: formValue.preferences.theme,
},
};
this.userService.updateUser(this.userId, userDto).subscribe({
next: () => this.showSuccess('Profile updated'),
error: (err) => this.showError(err.message),
});
}
Deeply Nested Forms
this.form = this.fb.group({
// ... other fields
shippingAddress: this.fb.group({
street: [''],
city: [''],
country: this.fb.group({
code: [''],
name: [''],
}),
}),
});
<div formGroupName="shippingAddress">
<input formControlName="street">
<div formGroupName="country">
<input formControlName="code">
<input formControlName="name">
</div>
</div>
Quiz
1. How do you access a nested form control?
2. What is the difference between setValue and patchValue?
3. Why map API DTOs to form models?
Flashcards
Question
How do you create nested form groups?
Click to reveal answer
Answer
this.fb.group({ address: this.fb.group({ city: [''] }) }) — nest FormGroup inside FormGroup.
Question
setValue vs patchValue?
Click to reveal answer
Answer
setValue requires all controls. patchValue updates only specified controls.
Question
Why map API DTOs to form models?
Click to reveal answer
Answer
Separates transport from UI, provides type safety, and makes forms testable.
Revision Notes
Key Takeaways
- 1. Nested FormGroups mirror nested object shapes
- 2. formGroupName binds nested groups in templates
- 3. setValue requires all controls; patchValue is partial
- 4. Map API DTOs to form models for type safety
Interview Tips
- • Explain how nested groups align with data models
- • Be ready to describe setValue vs patchValue
- • Mention DTO mapping for clean architecture
Cheat Sheet
Nested Forms Cheat Sheet
Nested group:
this.fb.group({
address: this.fb.group({
city: [''],
}),
});
Template:
<div formGroupName="address">
<input formControlName="city">
</div>
Access nested control:
this.form.get('address.city');
setValue vs patchValue:
- setValue: all controls required
- patchValue: partial updates only