Angular: формы

Template-driven vs Reactive Forms

  • Template-driven — логика формы в шаблоне (директивы ngModel), подходит для простых форм.
  • Reactive (model-driven) — форма описывается в коде (FormControl, FormGroup), лучше масштабируется и тестируется.

Состояния контрола (CSS-классы)

СостояниеКлассы
Взаимодействиеng-touched / ng-untouched
Валидностьng-valid / ng-invalid
Изменение данныхng-dirty / ng-pristine
  • touched — контрол потерял фокус (произошёл blur) хотя бы раз, независимо от того, менялось ли значение.
  • pristine — данные ещё не менялись; dirty — пользователь изменил данные.

AbstractControl

Абстрактный класс — основа для form controls и form groups в reactive forms. Предоставляет общие свойства и методы:

  • Валидация: valid, invalid, errors, setErrors().
  • Значение: value, patchValue(), reset().
  • Асинхронность: setAsyncValidators(), updateValueAndValidity().
  • События: valueChanges, statusChanges.
  • Композиция: addControl(), removeControl(), get().
  • UI-флаги: touched, dirty.

ControlValueAccessor & NG_VALUE_ACCESSOR

Реализация ControlValueAccessor + предоставление токена NG_VALUE_ACCESSOR позволяет создавать кастомные form-контролы, интегрированные с Forms API (two-way binding, валидация).

@Component({
  selector: "app-custom-control",
  template: "...",
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomControlComponent),
      multi: true,
    },
  ],
})
export class CustomControlComponent implements ControlValueAccessor {
  value: any;
  writeValue(value: any): void { this.value = value; }
  registerOnChange(fn: any): void { this.onChange = fn; }
  registerOnTouched(fn: any): void { this.onTouched = fn; }
  setDisabledState(isDisabled: boolean): void {}
  private onChange = () => {};
  private onTouched = () => {};
}