FAST Element предоставляет удобный механизм для создания веб-компонентов с реактивными свойствами и встроенной поддержкой валидации данных. В основе валидации лежат реактивные свойства (reactive properties), которые могут быть связаны с атрибутами HTML, что позволяет контролировать входные данные на уровне компонента.
Для объявления реактивного свойства используется декоратор
@attr или объектная конфигурация свойства в классе
компонента:
import { FASTElement, html, css, attr } from "@microsoft/fast-element";
class UserInput extends FASTElement {
@attr({ mode: "fromView" })
username;
@attr({ mode: "fromView" })
email;
}
Свойства с режимом fromView автоматически
синхронизируются с пользовательским вводом, что делает их удобными для
проверки и валидации.
FAST Element не предоставляет встроенных формальных валидаторов
наподобие React Hook Form, но поддерживает декларативное
управление состоянием свойства и его валидируемость
через геттеры/сеттеры и подписки на изменения:
class UserInput extends FASTElement {
@attr username;
usernameChanged(oldValue, newValue) {
this.isUsernameValid = /^[a-zA-Z0-9_]{3,15}$/.test(newValue);
}
}
username.Также можно использовать вычисляемые свойства:
get usernameError() {
if (!this.username) return "Поле обязательно для заполнения";
if (!/^[a-zA-Z0-9_]{3,15}$/.test(this.username)) return "Недопустимые символы";
return "";
}
FAST Element использует декларативный HTML-шаблон с привязками через
${}. Валидацию удобно интегрировать прямо в шаблон:
const template = html<UserInput>`
<label>
Логин:
<input type="text"
value="${x => x.username}"
@input="${(x, c) => x.username = c.event.target.value}">
</label>
<div class="error" if.bind="${x => x.usernameError}">
${x => x.usernameError}
</div>
`;
if.bind позволяет динамически отображать блок
ошибки только при наличии сообщения.@input синхронизирует значение поля с
реактивным свойством компонента.Для чисел и сложных объектов рекомендуется использовать настраиваемые сеттеры или вспомогательные методы:
class UserInput extends FASTElement {
@attr age;
ageChanged(oldValue, newValue) {
this.ageError = "";
const numeric = Number(newValue);
if (isNaN(numeric)) this.ageError = "Должно быть числом";
else if (numeric < 0 || numeric > 120) this.ageError = "Недопустимый возраст";
}
}
В шаблоне это интегрируется аналогично текстовому полю:
<input type="number"
value="${x => x.age}"
@input="${(x, c) => x.age = c.event.target.value}">
<div class="error" if.bind="${x => x.ageError}">
${x => x.ageError}
</div>
Для повторного использования логики валидации удобно создавать функции-валидаторы:
function required(value) {
return value ? "" : "Поле обязательно";
}
function minLength(value, length) {
return value.length >= length ? "" : `Минимум ${length} символов`;
}
function emailFormat(value) {
return /\S+@\S+\.\S+/.test(value) ? "" : "Неверный формат email";
}
Использование в компоненте:
class UserInput extends FASTElement {
@attr email;
get emailError() {
return required(this.email) || emailFormat(this.email);
}
}
FAST Element поддерживает асинхронные операции через методы жизненного цикла или реакции на изменения свойств:
class UserInput extends FASTElement {
@attr username;
usernameAvailable = true;
async usernameChanged(oldValue, newValue) {
if (!newValue) return;
this.usernameAvailable = await checkUsernameAvailability(newValue);
}
}
async function checkUsernameAvailability(username) {
const response = await fetch(`/api/check-username?username=${username}`);
const data = await response.json();
return data.available;
}
В шаблоне можно отобразить статус:
<div class="error" if.bind="${x => !x.usernameAvailable}">
Имя пользователя уже занято
</div>
FAST Element позволяет комбинировать несколько валидаторов для одного поля, используя массив функций:
const validators = [
required,
value => minLength(value, 3),
emailFormat
];
function validate(value) {
for (const fn of validators) {
const error = fn(value);
if (error) return error;
}
return "";
}
Для форм с FAST Element полезно агрегировать ошибки всех полей:
class UserForm extends FASTElement {
@attr username;
@attr email;
get isValid() {
return !this.usernameError && !this.emailError;
}
submit() {
if (this.isValid) {
// отправка данных на сервер
}
}
}
Привязка кнопки:
<button ?disabled.bind="${x => !x.isValid}" @click="${x => x.submit()}">
Отправить
</button>
Это позволяет полностью управлять состоянием формы на уровне компонента, не подключая сторонние библиотеки.
propertyChanged методы —
проверка значений при изменении.${} и
if.bind) — динамическое отображение ошибок.Эта структура позволяет строить сложные формы с многоуровневой валидацией, сохраняя реактивность и высокую читаемость кода.