Forms
Reactive forms & custom validation
Typed reactive forms, sync/async validators and ControlValueAccessor.
Reactive forms define the model in the class with FormGroup/FormControl/FormArray, giving an explicit, testable, immutable snapshot of form state — preferred over template-driven forms for anything non-trivial.
A reactive form is a spreadsheet model of the UI: the data lives in cells you control in code, and the inputs are just views onto those cells.
Key concepts
1
Angular’s typed forms infer value types, so form.value is strongly typed and refactors safely. Custom validators are functions returning an errors object or null; async validators return an observable/promise (e.g. server-side uniqueness checks) and set the pending state while running.
typed formsCustom validatorsasync validatorsform.valuepending
2
ControlValueAccessor lets a custom component participate in a form as a first-class control, so formControlName works on your own widgets.
`ControlValueAccessor`ControlValueAccessorformControlName
3
Pitfall: subscribing to valueChanges without takeUntilDestroyed leaks. Best practice: debounce async validators and mark controls updateOn: 'blur' for expensive checks. Interview angle: implement a cross-field validator (password confirm) at the group level.
Pitfall:Best practice:Interview angle:valueChangestakeUntilDestroyed
typescript
const form = new FormGroup({
email: new FormControl('', {
nonNullable: true,
validators: [Validators.required, Validators.email],
asyncValidators: [uniqueEmailValidator(api)],
updateOn: 'blur',
}),
password: new FormControl('', [Validators.minLength(8)]),
}, { validators: passwordsMatch });
form.valueChanges.pipe(takeUntilDestroyed()).subscribe(v => console.log(v));