Spec-Zone.ru › Angular

Формы в Angular

Обработка пользовательского ввода с помощью форм — основа многих распространённых приложений.

Приложения используют формы, чтобы пользователи могли входить в систему, обновлять профиль, вводить конфиденциальную информацию и выполнять множество других задач по вводу данных.

Angular предлагает два разных подхода к обработке пользовательского ввода с помощью форм: реактивный и на основе шаблонов.

Оба подхода позволяют получать события ввода пользователя из представления, проверять введённые данные, создавать форму и модель данных, а также отслеживать изменения.

СОВЕТ: Если вы ищете новые Signal Forms, ознакомьтесь с нашим руководством по основам Signal Forms!

В этом руководстве приведена информация, которая поможет выбрать тип формы, наиболее подходящий для вашей ситуации. Здесь рассматриваются общие строительные блоки, используемые в обоих подходах. Также кратко описаны ключевые различия между ними и показано, как эти различия проявляются при настройке, передаче данных и тестировании.

Выбор подхода

Реактивные формы и формы на основе шаблонов по-разному обрабатывают данные формы и управляют ими. У каждого подхода есть свои преимущества.

Формы Подробности
Реактивные формы Обеспечивают прямой и явный доступ к базовой объектной модели формы. По сравнению с формами на основе шаблонов они надёжнее: их проще масштабировать, повторно использовать и тестировать. Если формы играют ключевую роль в вашем приложении или вы уже используете реактивные шаблоны при его создании, выбирайте реактивные формы.
Формы на основе шаблонов Используют директивы в шаблоне для создания базовой объектной модели и управления ею. Они подходят для добавления простой формы в приложение, например формы подписки на рассылку по электронной почте. Их легко добавить в приложение, но масштабируются они хуже, чем реактивные формы. Если требования к форме и её логика очень просты и могут полностью обрабатываться в шаблоне, формы на основе шаблонов могут стать хорошим выбором.

Ключевые различия

В следующей таблице приведены основные различия между реактивными формами и формами на основе шаблонов.

Реактивные На основе шаблонов
Настройка модели формы Явная, создаётся в классе компонента Неявная, создаётся директивами
Модель данных Структурированная и неизменяемая Неструктурированная и изменяемая
Передача данных Синхронная Асинхронная
Проверка формы Функции Директивы

Масштабируемость

Если формы занимают центральное место в вашем приложении, масштабируемость очень важна. Возможность повторно использовать модели форм в разных компонентах имеет решающее значение.

Реактивные формы масштабируются лучше, чем формы на основе шаблонов. Они обеспечивают прямой доступ к базовому API форм и используют синхронную передачу данных между представлением и моделью данных, что упрощает создание крупных форм. Для тестирования реактивных форм требуется меньше настроек, а для корректной проверки обновлений и валидации формы не нужно глубоко разбираться в обнаружении изменений.

Формы на основе шаблонов предназначены для простых сценариев и хуже подходят для повторного использования. Они скрывают базовый API форм и используют асинхронную передачу данных между представлением и моделью данных. Абстракция форм на основе шаблонов влияет и на тестирование. Для корректного выполнения тестов необходимо вручную запускать обнаружение изменений, а настройка требует больше усилий.

Настройка модели формы

И реактивные формы, и формы на основе шаблонов отслеживают изменения значений между элементами ввода формы, с которыми взаимодействуют пользователи, и данными формы в модели компонента. В основе обоих подходов лежат общие строительные блоки, но способы создания и управления экземплярами общих элементов управления формы различаются.

Общие базовые классы форм

И реактивные формы, и формы на основе шаблонов построены на следующих базовых классах.

Базовые классы Подробности
FormControl Отслеживает значение и состояние проверки отдельного элемента управления формы.
FormGroup Отслеживает те же значения и состояние для набора элементов управления формы.
FormArray Отслеживает те же значения и состояние для массива элементов управления формы.
ControlValueAccessor Создаёт связующее звено между экземплярами Angular FormControl и встроенными элементами DOM.

Настройка реактивных форм

В реактивных формах модель формы задаётся непосредственно в классе компонента. Директива [formControl] связывает явно созданный экземпляр FormControl с определённым элементом формы в представлении, используя внутренний адаптер значения.

В следующем компоненте с помощью реактивных форм реализовано поле ввода для одного элемента управления. В этом примере модель формы — это экземпляр FormControl.

import {Component} from '@angular/core';
import {FormControl, ReactiveFormsModule} from '@angular/forms';

@Component({
  selector: 'app-reactive-favorite-color',
  template: ` Favorite Color: <input type="text" [formControl]="favoriteColorControl" /> `,
  imports: [ReactiveFormsModule],
})
export class FavoriteColorReactive {
  favoriteColorControl = new FormControl('');
}

ВАЖНО: В реактивных формах источником истины является модель формы; через директиву [formControl] на элементе <input> она в любой момент времени предоставляет значение и состояние элемента формы.

Настройка форм на основе шаблонов

В формах на основе шаблонов модель формы неявная, а не явная. Директива NgModel создаёт экземпляр FormControl для заданного элемента формы и управляет им.

В следующем компоненте с помощью форм на основе шаблонов реализовано то же поле ввода для одного элемента управления.

import {Component, signal} from '@angular/core';
import {FormsModule} from '@angular/forms';

@Component({
  selector: 'app-template-favorite-color',
  template: ` Favorite Color: <input type="text" [(ngModel)]="favoriteColor" /> `,
  imports: [FormsModule],
})
export class FavoriteColorTemplate {
  favoriteColor = signal('');
}

ВАЖНО: В форме на основе шаблонов источником истины является шаблон. Директива NgModel автоматически управляет экземпляром FormControl.

Передача данных в формах

Если в приложении есть форма, Angular должен поддерживать синхронизацию представления с моделью компонента, а модели компонента — с представлением. Когда пользователи изменяют значения и делают выбор в представлении, новые значения должны отражаться в модели данных. Аналогично, когда программная логика изменяет значения в модели данных, эти значения должны отражаться в представлении.

Реактивные формы и формы на основе шаблонов по-разному обрабатывают передачу данных, поступающих от пользователя или в результате программных изменений. На следующих диаграммах показаны оба типа потока данных для каждого типа формы на примере поля ввода любимого цвета, определённого выше.

Передача данных в реактивных формах

В реактивных формах каждый элемент формы в представлении напрямую связан с моделью формы (экземпляром FormControl). Обновления из представления в модель и из модели в представление выполняются синхронно и не зависят от способа отображения пользовательского интерфейса.

На диаграмме передачи данных из представления в модель показано, как данные передаются при изменении значения поля ввода в представлении, в соответствии со следующими шагами:

  1. Пользователь вводит значение в элемент ввода — в данном случае любимый цвет синий.
  2. Элемент ввода формы генерирует событие "input" с последним значением.
  3. Слушающий события элемента ввода формы ControlValueAccessor немедленно передаёт новое значение экземпляру FormControl.
  4. Экземпляр FormControl передаёт новое значение через Observable valueChanges.
  5. Все подписчики Observable valueChanges получают новое значение.

Вводит данные в поле ввода

Генерирует событие 'input'

Вызывает setValue() для FormControl

Генерирует событие 'valueChanges' для наблюдателей

Пользователь

<input>

ControlValueAccessor

FormControl

Наблюдатели

Диаграмма «модель — представление» показывает, как программное изменение модели передается представлению с помощью следующих шагов.

  1. Пользователь вызывает метод favoriteColorControl.setValue(), который обновляет значение FormControl.
  2. Экземпляр FormControl передает новое значение через наблюдаемый объект valueChanges.
  3. Все подписчики наблюдаемого объекта valueChanges получают новое значение.
  4. Аксессор значения элемента управления, связанный с элементом ввода формы, обновляет значение элемента.

Вызывает setValue() для FormControl

Уведомляет ControlValueAccessor

Генерирует событие 'valueChanges' для наблюдателей

Обновляет значение элемента <input>

Пользователь

<input>

ControlValueAccessor

FormControl

Наблюдатели

Поток данных в формах, управляемых шаблонами

В формах, управляемых шаблонами, каждый элемент формы связан с директивой, которая управляет моделью формы внутри себя.

Диаграмма «представление — модель» показывает, как передаются данные при изменении значения поля ввода в представлении. Процесс состоит из следующих шагов.

  1. Пользователь вводит Blue в элемент ввода.
  2. Элемент ввода генерирует событие "input" со значением Blue.
  3. Аксессор значения элемента управления, связанный с элементом ввода, вызывает метод setValue() экземпляра FormControl.
  4. Экземпляр FormControl передает новое значение через наблюдаемый объект valueChanges.
  5. Все подписчики наблюдаемого объекта valueChanges получают новое значение.
  6. Аксессор значения элемента управления также вызывает метод NgModel.viewToModelUpdate(), который генерирует событие ngModelChange.
  7. Поскольку в шаблоне компонента для свойства favoriteColor используется двусторонняя привязка данных, свойству favoriteColor компонента присваивается значение, переданное событием ngModelChange (Blue).

Вводит текст в поле

Вызывает событие 'input'

Вызывает setValue() для FormControl

Вызывает событие 'valueChanges' для наблюдателей

Вызывает viewToModelUpdate()

Вызывает событие ngModelChange

Обновляет значение свойства, связанного двусторонней привязкой

Пользователь

<input>

ControlValueAccessor

FormControl

NgModel

Наблюдатели

Компонент

Двусторонняя привязка

Диаграмма передачи данных от модели к представлению показывает, как данные проходят от модели к представлению, когда значение favoriteColor меняется с Синего на Красный, в ходе следующих шагов

  1. Значение favoriteColor обновляется в компоненте.
  2. Начинается обнаружение изменений.
  3. Во время обнаружения изменений для экземпляра директивы NgModel вызывается хук жизненного цикла ngOnChanges, поскольку изменилось значение одного из входных параметров.
  4. Метод ngOnChanges() ставит в очередь асинхронную задачу для установки значения внутреннего экземпляра FormControl.
  5. Обнаружение изменений завершается.
  6. При следующем такте выполняется задача установки значения экземпляра FormControl.
  7. Экземпляр FormControl передает последнее значение через observable valueChanges.
  8. Все подписчики observable valueChanges получают новое значение.
  9. Аксессор значения элемента управления обновляет элемент ввода формы в представлении, передавая ему последнее значение favoriteColor.

Обновляет значение свойства

Запускает обнаружение изменений

Асинхронные действия запускают второй цикл обнаружения изменений

Второе обнаружение изменений

Вызывает событие 'valueChanges' для наблюдателей

ControlValueAccessor получает событие valueChanges

Устанавливает значение в элементе управления

FormControl

Наблюдатели

ControlValueAccessor

<input>

Первое обнаружение изменений

Асинхронно устанавливает значение FormControl

NgModel

FormControl

Компонент

Свойство, связанное с NgModel

ПРИМЕЧАНИЕ: NgModel запускает второй цикл обнаружения изменений, чтобы избежать ошибок ExpressionChangedAfterItHasBeenChecked, поскольку изменение значения происходит во входной привязке.

Изменяемость модели данных

Метод отслеживания изменений влияет на эффективность вашего приложения.

Формы Подробности
Реактивные формы Поддерживайте чистоту модели данных, предоставляя её в виде неизменяемой структуры данных. Каждый раз, когда в модели данных происходит изменение, экземпляр FormControl возвращает новую модель данных, а не обновляет существующую. Это позволяет отслеживать отдельные изменения модели данных с помощью observable-контрола. Обнаружение изменений работает эффективнее, поскольку обновлять данные нужно только при отдельных изменениях. Поскольку обновления данных следуют реактивным шаблонам, вы можете интегрировать операторы observable для преобразования данных.
Формы, управляемые шаблонами Используйте изменяемость и двустороннюю привязку данных, чтобы обновлять модель данных в компоненте по мере изменений в шаблоне. Поскольку при использовании двусторонней привязки данных отдельные изменения модели данных не отслеживаются, обнаружение изменений менее эффективно определяет, когда требуются обновления.

Разница показана в предыдущих примерах с элементом ввода любимого цвета.

  • В реактивных формах экземпляр FormControl всегда возвращает новое значение при обновлении значения контрола
  • В формах, управляемых шаблонами, свойство любимого цвета всегда изменяется на новое значение

Проверка форм

Проверка — неотъемлемая часть управления любым набором форм. Angular предоставляет набор встроенных валидаторов, а также возможность создавать собственные валидаторы, будь то проверка обязательных полей или запрос к внешнему API для проверки существующего имени пользователя.

Формы Подробности
Реактивные формы Определяйте собственные валидаторы как функции, получающие контрол для проверки
Формы, управляемые шаблонами Связаны с директивами шаблона; необходимо предоставлять собственные директивы-валидаторы, оборачивающие функции проверки

Дополнительную информацию см. в разделе Проверка форм.

Тестирование

Тестирование играет важную роль в сложных приложениях. Более простая стратегия тестирования полезна для проверки корректной работы форм. Реактивные формы и формы, управляемые шаблонами, в разной степени зависят от отрисовки пользовательского интерфейса при выполнении проверок на основе изменений контролов и полей формы. В следующих примерах показан процесс тестирования реактивных форм и форм, управляемых шаблонами.

Тестирование реактивных форм

Реактивные формы обеспечивают относительно простую стратегию тестирования, поскольку предоставляют синхронный доступ к форме и моделям данных, а также позволяют тестировать их без отрисовки пользовательского интерфейса. В этих тестах состояние и данные запрашиваются и изменяются через контрол без взаимодействия с циклом обнаружения изменений.

В следующих тестах используются компоненты любимого цвета из предыдущих примеров, чтобы проверить потоки данных от представления к модели и от модели к представлению для реактивной формы.

Проверка потока данных от представления к модели

В первом примере выполняются следующие действия для проверки потока данных от представления к модели.

  1. Найдите в представлении элемент ввода формы и создайте для теста пользовательское событие "input".
  2. Задайте для ввода новое значение Red и отправьте событие "input" элементу ввода формы.
  3. Убедитесь, что значение favoriteColorControl компонента совпадает со значением элемента ввода.
it('should update the value of the input field', () => {
    const input = fixture.nativeElement.querySelector('input');
    const event = createNewEvent('input');

    input.value = 'Red';
    input.dispatchEvent(event);

    expect(fixture.componentInstance.favoriteColorControl.value).toEqual('Red');
  });

В следующем примере выполняются действия для проверки потока данных от модели к представлению.

  1. Используйте favoriteColorControl, экземпляр FormControl, чтобы задать новое значение.
  2. Найдите в представлении элемент ввода формы.
  3. Убедитесь, что новое значение, заданное для контрола, совпадает со значением элемента ввода.
it('should update the value in the control', () => {
    component.favoriteColorControl.setValue('Blue');

    const input = fixture.nativeElement.querySelector('input');

    expect(input.value).toBe('Blue');
  });

Тестирование форм, управляемых шаблонами

Написание тестов для форм, управляемых шаблонами, требует подробного знания процесса обнаружения изменений и понимания того, как директивы выполняются в каждом цикле, чтобы убедиться, что элементы запрашиваются, тестируются или изменяются в нужное время.

В следующих тестах используются упомянутые ранее компоненты любимого цвета, чтобы проверить потоки данных от представления к модели и от модели к представлению для формы, управляемой шаблонами.

Следующий тест проверяет поток данных от представления к модели.

it('should update the favorite color in the component', async () => {
    const input = fixture.nativeElement.querySelector('input');
    const event = createNewEvent('input');

    input.value = 'Red';
    input.dispatchEvent(event);

    await fixture.whenStable();

    expect(component.favoriteColor()).toEqual('Red');
  });

Ниже приведены действия, выполняемые в тесте потока данных от представления к модели.

  1. Найдите в представлении элемент ввода формы и создайте для теста пользовательское событие "input".
  2. Задайте для ввода новое значение Red и отправьте событие "input" элементу ввода формы.
  3. Запустите обнаружение изменений с помощью тестового стенда.
  4. Убедитесь, что значение свойства компонента favoriteColor совпадает со значением элемента ввода.

Следующий тест проверяет поток данных от модели к представлению.

it('should update the favorite color on the input field', async () => {
    component.favoriteColor.set('Blue');

    await fixture.whenStable();

    const input = fixture.nativeElement.querySelector('input');
    expect(input.value).toBe('Blue');
  });

Ниже приведены действия, выполняемые в тесте потока данных от модели к представлению.

  1. Используйте экземпляр компонента, чтобы задать значение свойства favoriteColor.
  2. Запустите обнаружение изменений с помощью тестового стенда.
  3. Используйте await fixture.whenStable(), чтобы дождаться следующей отрисовки.
  4. Найдите в представлении элемент ввода формы.
  5. Убедитесь, что значение элемента ввода совпадает со значением свойства favoriteColor в экземпляре компонента.

Следующие шаги

Дополнительные сведения о реактивных формах см. в следующих руководствах:

Реактивные формы Проверка форм Динамические формы

Дополнительные сведения о формах, управляемых шаблонами, см. в следующих руководствах:

Руководство по формам, управляемым шаблонами Проверка форм Справочник по API директивы NgForm

Super-powered by Google ©2010–2025.
Code licensed under an MIT-style License. Documentation licensed under CC BY 4.0.
https://angular.dev/guide/forms

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API