Stencil — это современный фреймворк для создания веб-компонентов с использованием стандартов веб-технологий. Он позволяет разработчикам создавать компоненты, которые могут работать в любых современных браузерах и быть интегрированы в любые существующие приложения, используя такие технологии как JavaScript, TypeScript, HTML и CSS. Важной частью разработки любого приложения является валидация данных, особенно когда речь идет о компонентах пользовательского интерфейса.
Валидация входных данных позволяет гарантировать, что данные, поступающие в компонент, соответствуют определенным стандартам или ограничениям, прежде чем они будут использованы для изменения состояния компонента или отправки на сервер. В Stencil эта задача решается с помощью встроенных механизмов, которые обеспечивают как синхронную, так и асинхронную валидацию.
Stencil использует декораторы для объявления свойств компонента. Эти свойства могут быть валидированы с помощью стандартных механизмов JavaScript или TypeScript. Один из распространенных способов валидации — использование типов данных, задаваемых для каждого свойства компонента. Типы обеспечивают базовую проверку на соответствие, однако для более сложных проверок можно использовать дополнительные методы.
@Component({
tag: 'app-input',
styleUrl: 'app-input.css',
shadow: true
})
export class AppInput {
@Prop() value: string;
@Watch('value')
validateValue(newValue: string) {
if (newValue.length < 3) {
console.error('Значение должно быть не менее 3 символов');
}
}
}
В этом примере используется декоратор @Prop(), который
определяет свойство value компонента. При изменении этого
свойства срабатывает метод validateValue, который
проверяет, что длина значения больше или равна 3 символам. Такой подход
позволяет выполнять валидацию при каждом изменении данных.
Иногда необходимо выполнить асинхронную валидацию данных, например, для проверки уникальности значения на сервере или выполнения других сетевых запросов. В таких случаях можно использовать асинхронные функции внутри методов валидации.
@Component({
tag: 'app-username',
styleUrl: 'app-username.css',
shadow: true
})
export class AppUsername {
@Prop() username: string;
@Watch('username')
async validateUsername(newUsername: string) {
if (newUsername.length < 3) {
console.error('Имя пользователя должно быть не менее 3 символов');
return;
}
const isUsernameTaken = await this.checkUsernameAvailability(newUsername);
if (isUsernameTaken) {
console.error('Это имя пользователя уже занято');
}
}
async checkUsernameAvailability(username: string): Promise<boolean> {
// Здесь можно выполнить запрос к серверу
const response = await fetch(`/api/check-username?username=${username}`);
const data = await response.json();
return data.isTaken;
}
}
В этом примере метод validateUsername выполняет
асинхронную проверку доступности имени пользователя. В случае, если имя
уже занято, выводится ошибка, которая информирует пользователя о
проблеме.
Stencil позволяет создавать кастомные валидаторы, которые могут быть
использованы в компонентах для более сложных проверок. Такие валидаторы
могут быть реализованы как отдельные функции или методы, которые
принимают данные и возвращают либо true, либо ошибку
валидации.
function isValidEmail(email: string): boolean {
const re = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return re.test(email);
}
@Component({
tag: 'app-email',
styleUrl: 'app-email.css',
shadow: true
})
export class AppEmail {
@Prop() email: string;
@Watch('email')
validateEmail(newEmail: string) {
if (!isValidEmail(newEmail)) {
console.error('Неверный формат email');
}
}
}
Здесь функция isValidEmail реализует проверку формата
email с помощью регулярного выражения. Метод validateEmail
использует этот валидатор для проверки введенного email и выводит
ошибку, если формат неверный.
После выполнения валидации важно правильно обработать ошибки и уведомить пользователя о некорректных данных. В Stencil можно использовать такие подходы, как отображение текстовых сообщений рядом с полями ввода, либо визуальное выделение ошибок.
@Component({
tag: 'app-input',
styleUrl: 'app-input.css',
shadow: true
})
export class AppInput {
@Prop() value: string;
@State() errorMessage: string;
@Watch('value')
validateValue(newValue: string) {
if (newValue.length < 3) {
this.errorMessage = 'Значение должно быть не менее 3 символов';
} else {
this.errorMessage = '';
}
}
render() {
return (
<div>
<input type="text" value={this.value} />
{this.errorMessage && <p class="error">{this.errorMessage}</p>}
</div>
);
}
}
В этом примере введенное значение проверяется на минимальную длину.
Если длина меньше 3 символов, отображается сообщение об ошибке.
Визуально это сообщение выводится в элемент <p> с
классом error.
Stencil также поддерживает использование форм с валидацией на уровне всего компонента. Это позволяет валидировать несколько полей данных одновременно, а также управлять состоянием отправки формы.
@Component({
tag: 'app-form',
styleUrl: 'app-form.css',
shadow: true
})
export class AppForm {
@State() name: string;
@State() email: string;
@State() errorMessage: string;
validateForm() {
if (!this.name || !this.email) {
this.errorMessage = 'Все поля обязательны для заполнения';
return false;
}
if (!isValidEmail(this.email)) {
this.errorMessage = 'Неверный формат email';
return false;
}
this.errorMessage = '';
return true;
}
handleSubmit(event: Event) {
event.preventDefault();
if (this.validateForm()) {
console.log('Форма отправлена');
}
}
render() {
return (
<form onSub mit={(event) => this.handleSubmit(event)}>
<input type="text" value={this.name} onIn put={(event) => this.name = (event.target as HTMLInputElement).value} />
<input type="email" value={this.email} onIn put={(event) => this.email = (event.target as HTMLInputElement).value} />
{this.errorMessage && <p class="error">{this.errorMessage}</p>}
<button type="submit">Отправить</button>
</form>
);
}
}
Здесь реализована форма с двумя полями — для имени и email. При отправке формы выполняется валидация, которая проверяет обязательность заполнения полей и корректность email. Если данные некорректны, выводится сообщение об ошибке.
Stencil можно интегрировать с внешними библиотеками для более сложной
валидации данных. Одним из популярных решений является библиотека
yup, которая предоставляет мощные средства для валидации и
обработки ошибок.
yupimport * as yup from 'yup';
@Component({
tag: 'app-form',
styleUrl: 'app-form.css',
shadow: true
})
export class AppForm {
@State() name: string;
@State() email: string;
@State() errorMessage: string;
schema = yup.object().shape({
name: yup.string().required('Имя обязательно'),
email: yup.string().email('Неверный формат email').required('Email обязателен'),
});
async validateForm() {
try {
await this.schema.validate({ name: this.name, email: this.email });
this.errorMessage = '';
return true;
} catch (error) {
this.errorMessage = error.message;
return false;
}
}
handleSubmit(event: Event) {
event.preventDefault();
this.validateForm().then(valid => {
if (valid) {
console.log('Форма отправлена');
}
});
}
render() {
return (
<form onSub mit={(event) => this.handleSubmit(event)}>
<input type="text" value={this.name} onIn put={(event) => this.name = (event.target as HTMLInputElement).value} />
<input type="email