Пользовательские элементы форм

FAST Element — это современная библиотека для разработки веб-компонентов с использованием стандартов Web Components и реактивного связывания данных. Основной единицей в FAST является custom element, который можно создавать, настраивать и использовать так же, как стандартные HTML-теги.


Определение пользовательского элемента

Для создания пользовательского элемента используется класс, наследующийся от FASTElement. Класс должен быть зарегистрирован с помощью функции customElements.define или через FASTElement.define.

Пример базового элемента формы:

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

const template = html<MyInputElement>`
  <label>${x => x.label}</label>
  <input type="text" value="${x => x.value}" @input="${x => x.handleInput()}"/>
`;

const styles = css`
  label {
    display: block;
    font-weight: bold;
    margin-bottom: 4px;
  }
  input {
    padding: 6px 8px;
    border: 1px solid #ccc;
    border-radius: 4px;
  }
`;

export class MyInputElement extends FASTElement {
  value = "";
  label = "Поле ввода";

  handleInput(event) {
    this.value = event.target.value;
  }
}

FASTElement.define({
  name: "my-input",
  template,
  styles,
  elementClass: MyInputElement
});

Ключевые моменты:

  • Шаблон (template) создаётся с использованием функции html и поддерживает привязку данных через стрелочные функции.
  • Стили (css) применяются локально к элементу и не влияют на глобальные стили.
  • Обработчики событий можно указывать через @event="${x => x.method()}".
  • Привязка к свойствам компонента происходит через ${x => x.property}.

Свойства и реактивность

FAST Element поддерживает реактивные свойства, которые автоматически обновляют DOM при изменении значения. Для реактивных свойств используется @observable или декларация свойств внутри класса.

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

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

class MyCheckbox extends FASTElement {
  @observable checked = false;
}
  • Изменение checked автоматически обновит все привязки в шаблоне.
  • Можно использовать вычисляемые свойства для динамических классов или атрибутов.

Управление формой через пользовательский элемент

Для сложных форм удобно объединять несколько элементов в один контейнер:

const formTemplate = html<MyFormElement>`
  <form @submit="${x => x.handleSubmit()}">
    <my-input label="Имя" value="${x => x.name}"></my-input>
    <my-input label="Email" value="${x => x.email}"></my-input>
    <button type="submit">Отправить</button>
  </form>
`;

class MyFormElement extends FASTElement {
  name = "";
  email = "";

  handleSubmit(event) {
    event.preventDefault();
    console.log("Данные формы:", { name: this.name, email: this.email });
  }
}

FASTElement.define({
  name: "my-form",
  template: formTemplate,
  elementClass: MyFormElement
});

Особенности:

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

Динамическая генерация элементов

FAST Element поддерживает генерацию коллекций с помощью директив repeat:

import { repeat } from "@microsoft/fast-element";

const todoTemplate = html<MyTodoList>`
  <ul>
    ${repeat(x => x.items, html<TodoItem>`
      <li>${x => x.text}</li>
    `)}
  </ul>
`;

class MyTodoList extends FASTElement {
  items = [{ text: "Сделать урок" }, { text: "Проверить почту" }];
}

FASTElement.define({
  name: "my-todo-list",
  template: todoTemplate,
  elementClass: MyTodoList
});
  • repeat позволяет создавать списки с реактивными данными.
  • Любое изменение массива элементов автоматически обновляет DOM.

Пользовательские атрибуты и свойства

FAST Element позволяет синхронизировать свойства класса с атрибутами HTML через @attr:

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

class MyButton extends FASTElement {
  @attr type = "button"; // Атрибут type синхронизирован с классом
}

FASTElement.define({
  name: "my-button",
  template: html<MyButton>`<button type="${x => x.type}"><slot></slot></button>`,
  elementClass: MyButton
});
  • Изменение атрибута type через HTML автоматически обновляет свойство type в классе.
  • Аналогично, изменение свойства через класс обновляет атрибут в DOM.

Поддержка слотов и контента

Для гибкой кастомизации формы используется <slot>:

const cardTemplate = html<MyCard>`
  <div class="card">
    <slot name="header"></slot>
    <slot></slot>
  </div>
`;

class MyCard extends FASTElement {}

FASTElement.define({
  name: "my-card",
  template: cardTemplate,
  elementClass: MyCard
});
  • Можно задавать именованные слоты (name="header") для заголовков или боковых панелей.
  • Слот позволяет пользователю вставлять любой HTML внутрь компонента, сохраняя реактивность и стилизацию.

Итоговые возможности для форм

Использование FAST Element позволяет создавать полностью реактивные, настраиваемые и модульные формы с минимальной зависимостью от сторонних библиотек. Библиотека обеспечивает:

  • Реактивные свойства и привязку данных.
  • Локальные стили, изолированные от глобального CSS.
  • Удобные директивы (repeat, when) для динамических интерфейсов.
  • События и управление состоянием формы через классы.
  • Интеграцию с другими Web Components без конфликтов.

Эти возможности делают FAST Element оптимальным инструментом для сложных пользовательских форм в современных веб-приложениях.