form-controller-lit
v2.3.0
Published
Реактивный контроллер для управления состоянием форм в Lit-приложениях.
Maintainers
Readme
Form Controller for Lit (v2)
Form Controller for Lit — это мощный и гибкий реактивный контроллер для управления состоянием форм в Lit-приложениях. Он упрощает обработку значений, валидацию, отслеживание состояния полей и отправку данных.
Ключевые фичи v2
- ✨ Директива
field: Максимально чистые и декларативные шаблоны без повторяющегося кода. - ⚡ Гибридная валидация: Используйте всю мощь Zod для типобезопасной валидации или выберите гибкую ручную настройку.
- 🧠 Умные режимы валидации: Полный контроль над UX с режимами
onChange,onBlur,onSubmitи прогрессивнымhybrid(по умолчанию). В режимеhybridвалидация срабатывает приblur, но переключается наonChange, если поле невалидно или форма была отправлена. - 🚀 Оптимизация с Debounce: Встроенная опция
debounceдля отложенной валидации. - 🎯 Декларативный API: Чистое и предсказуемое описание правил валидации.
- 💪 Кастомные сообщения: Легко переопределяйте сообщения об ошибках.
- 🏗️ DynamicForm Компонент: Готовый компонент для рендеринга форм на основе JSON-конфигурации и Zod схем. Подробнее в документации.
Установка
npm install form-controller-litДля использования валидации на основе Zod, вам также нужно установить zod:
npm install zodБыстрый старт (с Zod и директивой field)
Это рекомендуемый способ использования. Он обеспечивает максимальную типобезопасность и самый чистый код шаблонов.
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import { FormController, field } from 'form-controller-lit'; // Импортируем директиву
import { z } from 'zod';
// 1. Определяем схему валидации и выводим тип
const formSchema = z.object({
username: z.string().min(3, { message: 'Имя должно быть не менее 3 символов' }),
email: z.string().email({ message: 'Неверный формат email' }),
});
type FormValues = z.infer<typeof formSchema>;
@customElement('my-zod-form')
export class MyZodForm extends LitElement {
// 2. Инициализируем контроллер
form = new FormController<FormValues>(this, {
schema: formSchema,
initialValues: {
username: '',
email: '',
},
validationMode: 'hybrid', // 'onChange' | 'onBlur' | 'onSubmit' | 'hybrid' (по умолчанию)
});
async submit(values: FormValues) {
console.log('Отправка данных:', values);
await new Promise(r => setTimeout(r, 1000));
}
render() {
return html`
<form @submit=${(e: Event) => {
e.preventDefault();
this.form.submit(this.submit);
}}>
<div>
<label>Имя</label>
<!-- 3. Используем директиву field -->
<input ${field(this.form, 'username')} />
${this.form.touched.username && this.form.errors.username
? html`<small>${this.form.errors.username}</small>`
: ''}
</div>
<div>
<label>Email</label>
<input ${field(this.form, 'email')} />
${this.form.touched.email && this.form.errors.email
? html`<small>${this.form.errors.email}</small>`
: ''}
</div>
<button type="submit" ?disabled=${this.form.isSubmitting}>
${this.form.isSubmitting ? 'Отправка...' : 'Отправить'}
</button>
</form>
`;
}
}Продвинутое использование
Ручная валидация
Если вам не нужен Zod, используйте ручную настройку через свойство data. Директива field работает и в этом режиме.
const form = new FormController(this, {
data: {
password: {
initialValue: '',
validate: {
required: true,
min: { value: 8, message: 'Пароль должен быть не менее 8 символов' },
custom: (value) => !/[0-9]/.test(value) ? 'Пароль должен содержать хотя бы одну цифру.' : null,
},
},
},
});Встроенные правила: required, min, max, pattern, custom.
API
Опции конструктора
schema: Экземпляр схемы Zod.initialValues: Объект с начальными значениями (обязателен при использованииschema).data: Объект для ручной конфигурации полей.debounce: (Опционально) Задержка в мс для валидации в режимеonChange.validationMode: (Опционально)'onChange','onBlur','onSubmit'или'hybrid'(по умолчанию).
Основные свойства
values,errors,touched,isDirty,isValid,isSubmitting.
Основные методы и директивы
field(controller, fieldName): Директива для привязки элемента ввода к контроллеру. Автоматически управляет значением и событиямиinputиblur.setFieldValue(fieldName, value): Устанавливает значение поля. (В основном используется внутри директивыfield).handleBlur(fieldName): Обрабатывает событие потери фокуса. (В основном используется внутри директивыfield).submit(callback): Запускает валидацию и вызываетcallbackс данными формы.reset(): Сбрасывает форму.
Гайд по миграции с v1 на v2
Версия 2.0.0 вносит несколько обратно несовместимых изменений.
1. Изменение API валидации
validate теперь всегда является объектом.
Было (v1):
// 👎 Этот синтаксис больше не работает
validate: (value) => value.length > 0Стало (v2):
Используйте правило custom:
validate: {
custom: (value) => value.length > 0 ? null : 'Поле не может быть пустым'
}2. Регистрация полей в шаблоне (Важно!)
Вместо ручной привязки .value, @input и @blur теперь рекомендуется использовать директиву field.
Было (v1/v2 без директивы):
<input
.value=${this.form.values.name}
@input=${(e) => this.form.setFieldValue('name', e.target.value)}
@blur=${() => this.form.handleBlur('name')}
/>Стало (v2 с директивой):
import 'form-controller-lit/components/dynamicForm';
// ...
html`
<input ${field(this.form, 'name')} />
`Это изменение не является строго обязательным (старый способ все еще работает), но настоятельно рекомендуется для чистоты кода.
