FormAssociated API

FormAssociated API представляет собой механизм, позволяющий создавать настраиваемые элементы форм, полностью интегрированные с нативным поведением HTML-форм. Он обеспечивает взаимодействие с формой, обработку значений, валидацию и синхронизацию состояния, аналогично стандартным элементам <input> или <select>.

Основные концепции

  • Form-associated custom elements (FACE) — это настраиваемые элементы, которые могут быть ассоциированы с формой. Ассоциация позволяет элементу участвовать в отправке формы, реагировать на её события и поддерживать свойства value, name, disabled, required и другие.
  • Shadow DOM не мешает работе с FormAssociated API, так как взаимодействие с формой осуществляется через внутренний механизм ElementInternals.

ElementInternals

Ключевой компонент FormAssociated API — объект ElementInternals. Он предоставляет методы и свойства для интеграции с формой:

  • internals.form — возвращает родительскую форму или null, если элемент не внутри формы.
  • internals.setFormValue(value[, state]) — устанавливает значение элемента, которое будет отправлено вместе с формой. Опциональный параметр state позволяет хранить дополнительное внутреннее состояние.
  • internals.setValidity(flags, message, anchor) — задаёт состояние валидации элемента.
  • internals.validationMessage — возвращает сообщение о текущей ошибке валидации.
  • internals.checkValidity() — проверяет валидность элемента и возвращает true или false.
  • internals.reportValidity() — инициирует визуальное отображение ошибок валидации.

Создание форм-ассоциированного элемента

Для создания форм-ассоциированного элемента необходимо использовать опцию formAssociated: true в определении класса:

import { FASTElement, html, css } from "@microsoft/fast-element";

const template = html<MyInput>`<input type="text" .value="${x => x.value}" />`;

class MyInput extends FASTElement {
  static formAssociated = true; // Включение FormAssociated API

  internals;

  value = "";

  constructor() {
    super();
    this.internals = this.attachInternals(); // Подключение ElementInternals
  }

  connectedCallback() {
    super.connectedCallback();
    this.internals.setFormValue(this.value); // Инициализация значения для формы
  }

  valueChanged(prev, next) {
    this.internals.setFormValue(next); // Обновление значения при изменении
  }

  checkValidity() {
    return this.internals.checkValidity();
  }
}

FASTElement.define({ name: "my-input", template, styles: css`input { padding: 4px; }` }, MyInput);

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

События и синхронизация с формой

Форм-ассоциированные элементы могут реагировать на события формы:

  • formdata — событие, возникающее при создании данных формы перед отправкой.
  • reset — событие сброса формы. Можно определить поведение элемента при сбросе значений.

Пример обработки сброса:

connectedCallback() {
  super.connectedCallback();
  this.internals.form?.addEventListener('reset', () => {
    this.value = "";
    this.internals.setFormValue(this.value);
  });
}

Валидация и пользовательские ошибки

FormAssociated API позволяет полностью контролировать процесс валидации:

  • setValidity({ valueMissing: true }, "Поле обязательно") — установка ошибки, эквивалентной стандартной HTML-валидации.
  • checkValidity() — проверяет элемент и возвращает логический результат.
  • reportValidity() — отображает визуальное сообщение об ошибке.

Пример кастомной проверки:

validate() {
  if (!this.value || this.value.length < 3) {
    this.internals.setValidity({ customError: true }, "Минимум 3 символа");
  } else {
    this.internals.setValidity({});
  }
}

Свойства, интегрируемые с формой

FormAssociated API поддерживает синхронизацию следующих свойств:

  • name — имя поля, отправляемое с формой.
  • value — текущее значение.
  • disabled — блокировка элемента.
  • required — обязательность заполнения.

Пример синхронизации disabled:

disabledChanged(prev, next) {
  this.internals.ariaDisabled = next;
}

Преимущества использования FormAssociated API

  • Полная интеграция с HTML-формами без дополнительных обработчиков.
  • Поддержка стандартных методов валидации (checkValidity, reportValidity).
  • Возможность создания сложных кастомных элементов формы с сохранением нативного поведения.
  • Совместимость с Shadow DOM и реактивными свойствами FAST Element.

Особенности использования с FAST Element

  • Реактивные свойства FAST Element легко связываются с ElementInternals через геттеры и сеттеры.
  • Использование valueChanged позволяет автоматически синхронизировать значение элемента с формой.
  • Shadow DOM не мешает взаимодействию с формой, так как ElementInternals обеспечивает прямую связь с родительской формой.

FormAssociated API в сочетании с FAST Element открывает возможности создавать мощные, полностью настраиваемые элементы форм, сохраняющие нативное поведение и гибкость при работе с валидацией и формами в целом.