Реактивные формы
В реактивных формах (reactive forms) структура формы описывается в классе компонента, а шаблон только привязывает к ней поля. Так форма целиком видна в TypeScript: её легко проверять, менять из кода и тестировать. Для больших форм со сложными правилами обычно выбирают этот вид.
Описание формы в классе
Нужен ReactiveFormsModule в imports и классы FormGroup и FormControl:
// src/app/post-form/post-form.ts
import { Component } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'app-post-form',
imports: [ReactiveFormsModule],
templateUrl: './post-form.html',
})
export class PostForm {
form = new FormGroup({
title: new FormControl('', { nonNullable: true }),
body: new FormControl('', { nonNullable: true }),
});
}FormControl — одно поле с начальным значением, FormGroup — группа полей. Настройка nonNullable: true означает, что после сброса поле вернётся к пустой строке, а не к null.
Привязка в шаблоне
<!-- src/app/post-form/post-form.html -->
<form [formGroup]="form" (ngSubmit)="save()">
<input formControlName="title" placeholder="Заголовок" />
<textarea formControlName="body" placeholder="Текст"></textarea>
<button type="submit">Опубликовать</button>
</form>[formGroup] связывает тег формы с объектом form, а formControlName — каждое поле с элементом группы по имени. Атрибут name и ngModel здесь не нужны.
Отправка
// src/app/post-form/post-form.ts
private api = inject(PostApi);
save() {
const data = this.form.getRawValue();
this.api.createPost(data).subscribe(() => this.form.reset());
}getRawValue() возвращает объект { title, body } со строгими типами. После успешного запроса форма очищается. Не забудьте импортировать inject и PostApi.
Чтение и изменение из кода
У формы и каждого поля есть методы и свойства для работы из класса:
| Код | Что делает |
|---|---|
form.value | Текущие значения всех полей |
form.controls.title.value | Значение одного поля |
form.setValue({ title: 'A', body: 'B' }) | Задать все поля сразу |
form.patchValue({ title: 'A' }) | Задать только часть полей |
form.reset() | Вернуть начальные значения |
form.valueChanges | Observable, выдающий значения при каждом вводе |
Например, при редактировании статьи загруженные данные кладут в форму одной строкой: this.form.patchValue(post).
FormBuilder
Для больших форм new FormControl повторяется много раз. Сервис FormBuilder записывает то же короче:
// src/app/post-form/post-form.ts
import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'app-post-form',
imports: [ReactiveFormsModule],
templateUrl: './post-form.html',
})
export class PostForm {
private fb = inject(FormBuilder).nonNullable;
form = this.fb.group({
title: [''],
body: [''],
});
}Результат тот же: группа из двух полей, которые не бывают null. Шаблон не меняется.
Частая ошибка
Импортировать FormsModule вместо ReactiveFormsModule. Тогда сборка сообщит, что не может привязаться к formGroup, так как это неизвестное свойство элемента form. Для реактивных форм нужен именно ReactiveFormsModule.