I have a form that looks like this:
form = formGroup({
name:FormControl(''),
adress:new FormGroup({
city: new FOrmControl(''),
})
})
and I use two components
parent:
<form [formGroup]="form" (ngSubmit)="submit()">
<input matInput formControlName="name">
<child-component [group]="form.controls.adress"><child-component/>
</form>
child:
<form [formGroup]="group">
<input matInput formControlName="city">
</form>
Now my problem is that when I submit the form and city
is invalid, the red underline doesn't show.
How can submit have an effect on both parent and child?
Please try the below code:
parent.component.html
<form [formGroup]="form" (ngSubmit)="submit()">
<mat-form-field>
<input matInput formControlName="name" placeholder="Name">
<mat-error *ngIf="form.controls.name.invalid && (form.controls.name.dirty || form.controls.name.touched)">
Name is required
</mat-error>
</mat-form-field>
<app-child [group]="addressGroup"></app-child>
<button type="submit">Submit</button>
</form>
parent.component.ts
import { OnInit, Component } from '@angular/core';
import { ApiResponse } from '../models/apiResponse';
import { ChaptersViewModel } from '../models/chapters.model';
import { HomeService } from './home.service';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.scss']
})
export class ParentComponent implements OnInit {
form: FormGroup;
ngOnInit() {
this.form = new FormGroup({
name: new FormControl('', Validators.required),
address: new FormGroup({
city: new FormControl('', Validators.required),
}),
});
}
submit() {
this.markAllAsTouched(this.form);
if (this.form.valid) {
// Handle valid form submission
}
}
markAllAsTouched(group: FormGroup) {
Object.keys(group.controls).forEach((key) => {
const control = group.get(key);
if (control instanceof FormControl) {
control.markAsTouched();
} else if (control instanceof FormGroup) {
this.markAllAsTouched(control);
}
});
}
get addressGroup(): FormGroup {
return this.form.get('address') as FormGroup;
}
}
child.component.html
<form [formGroup]="group">
<mat-form-field>
<input matInput formControlName="city" placeholder="City">
<mat-error *ngIf="group.controls.city.invalid && (group.controls.city.dirty || group.controls.city.touched)">
City is required
</mat-error>
</mat-form-field>
</form>
child.component.ts
import { Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss']
})
export class ChildComponent {
@Input() group!: FormGroup;
constructor() { }
}