Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Реактивные формы

В реактивных формах (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.valueChangesObservable, выдающий значения при каждом вводе

Например, при редактировании статьи загруженные данные кладут в форму одной строкой: 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.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.