I use nested reactive form as FormControl.
Here is demo https://stackblitz.com/edit/angular-pmfq5z?file=app%2Fapp.component.ts
Issue: the main form is valid even if nested is invalid (try to clear required fields).
How the main form can be notified about nested form validity change?
The main form component:
import { Component, Input } from '@angular/core';
import { FormBuilder, FormGroup, ControlContainer, NgForm, Validators } from '@angular/forms';
@Component({
selector: 'my-app',
template: `
<h1>Form</h1>
<pre>Valid: {{ form.valid }}</pre>
<form [formGroup]="form" (ngSubmit)="onSubmit(form.value)" novalidate>
<label>name</label>
<input formControlName="name">
<app-address-form formControlName="address"></app-address-form>
<button>submit</button>
</form>
<ng-container *ngIf="submitData">
<span>submit data</span>
<pre>{{ submitData }}</pre>
</ng-container>
`
})
export class AppComponent {
@Input() name: string;
submitData = '';
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = fb.group({
name: fb.control('foo bar', Validators.required),
address: fb.control({
city: 'baz',
town: 'qux',
})
});
}
onSubmit(v: any) {
this.submitData = JSON.stringify(v, null, 2);
}
}
The nested form component:
import { Component, forwardRef } from '@angular/core';
import { ControlContainer, ControlValueAccessor, FormGroup, FormControl, NG_VALUE_ACCESSOR, NgControl, NgForm, Validators } from '@angular/forms';
// https://docs.google.com/presentation/d/e/2PACX-1vTS20UdnMGqA3ecrv7ww_7CDKQM8VgdH2tbHl94aXgEsYQ2cyjq62ydU3e3ZF_BaQ64kMyQa0INe2oI/pub?slide=id.g293d7d2b9d_1_1532
@Component({
selector: 'app-address-form',
template: `
<div [formGroup]="form">
<label>city</label>
<input formControlName="city" (blur)="onTouched()">
<label>town</label>
<input formControlName="town" (blur)="onTouched()">
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => AddressFormComponent)
}
]
})
export class AddressFormComponent implements ControlValueAccessor {
form: FormGroup = new FormGroup({
city: new FormControl('', Validators.required),
town: new FormControl('', Validators.required)
});
onTouched: () => void = () => {};
writeValue(v: any) {
this.form.setValue(v, { emitEvent: false });
}
registerOnChange(fn: (v: any) => void) {
this.form.valueChanges.subscribe(fn);
}
setDisabledState(disabled: boolean) {
disabled ? this.form.disable() : this.form.enable();
}
registerOnTouched(fn: () => void) {
this.onTouched = fn;
}
}