Валидация форм

Stencil предоставляет мощный инструмент для создания веб-компонентов с поддержкой декларативного программирования и реактивности. Одной из важнейших задач при работе с компонентами является валидация данных формы. В этой главе рассмотрим способы реализации валидации форм в приложениях, построенных на Stencil.

Основы валидации форм

Валидация формы — это процесс проверки данных, введённых пользователем, с целью убедиться в их корректности перед отправкой. В Stencil валидация может быть реализована на уровне компонента, при этом можно воспользоваться встроенными механизмами или добавить собственные.

В случае с Stencil валидация часто реализуется с использованием декларативных атрибутов, реактивных переменных и событий. Важным моментом является то, что Stencil позволяет интегрировать валидацию как на уровне пользовательского интерфейса, так и на уровне бизнес-логики, что даёт гибкость в реализации.

Основные этапы валидации

  1. Сбор данных формы На первом этапе необходимо собрать данные, введённые пользователем. В Stencil это можно сделать через двустороннее связывание данных с использованием @Prop() и @State().

  2. Применение проверок После того как данные формы собраны, они проверяются на соответствие заданным правилам. Это можно реализовать как через встроенные методы HTML-форм, так и через кастомные проверки, написанные вручную.

  3. Предоставление обратной связи пользователю На последнем этапе важно предоставить пользователю информацию о том, что он сделал что-то неправильно, например, подсветив поля ошибки или выведя текст сообщения.

Валидация с использованием HTML5 атрибутов

Stencil поддерживает все стандартные атрибуты валидации HTML5, такие как required, minlength, maxlength, pattern, и другие. Эти атрибуты могут быть добавлены к элементам формы, таким как <input>, <select>, <textarea>, для автоматической проверки данных при отправке формы.

<form>
  <label>
    Email:
    <input type="email" required />
  </label>
  <button type="submit">Отправить</button>
</form>

Пример выше показывает, как можно использовать встроенную валидацию для поля email. Если пользователь не введёт корректный email, форма не будет отправлена, и браузер автоматически отобразит сообщение об ошибке.

Реактивная валидация в Stencil

Для более сложных случаев, когда нужно выполнить дополнительные проверки, Stencil предлагает использовать реактивное связывание данных. С помощью @State() можно отслеживать состояние полей и производить валидацию в реальном времени.

Пример использования реактивной валидации:

import { Component, h, State } from '@stencil/core';

@Component({
  tag: 'custom-form',
  styleUrl: 'custom-form.css',
  shadow: true
})
export class CustomForm {
  @State() email: string = '';
  @State() emailError: string = '';

  validateEmail() {
    const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    this.emailError = emailRegex.test(this.email) ? '' : 'Некорректный email';
  }

  handleSubmit(event: Event) {
    event.preventDefault();
    this.validateEmail();
    if (!this.emailError) {
      // Отправить форму
    }
  }

  render() {
    return (
      <form onSub mit={(e) => this.handleSubmit(e)}>
        <label>
          Email:
          <input
            type="email"
            value={this.email}
            onIn put={(e) => (this.email = (e.target as HTMLInputElement).value)}
            onB lur={() => this.validateEmail()}
          />
        </label>
        {this.emailError && <p class="error">{this.emailError}</p>}
        <button type="submit">Отправить</button>
      </form>
    );
  }
}

В этом примере:

  • Поле для ввода email связано с состоянием email, который отслеживает значение поля.
  • При изменении значения поля происходит обновление состояния, а при потере фокуса (событие onBlur) запускается валидация.
  • Ошибка выводится, если введённый email не соответствует регулярному выражению.

Валидация нескольких полей

Когда форма состоит из нескольких полей, важно контролировать состояние всех этих полей. Stencil предоставляет удобные способы для этого. Каждое поле может иметь свою собственную логику валидации, а затем можно собрать все результаты в одном месте.

Пример валидации формы с несколькими полями:

@Component({
  tag: 'multi-field-form',
  styleUrl: 'multi-field-form.css',
  shadow: true
})
export class MultiFieldForm {
  @State() name: string = '';
  @State() email: string = '';
  @State() nameError: string = '';
  @State() emailError: string = '';

  validateName() {
    this.nameError = this.name ? '' : 'Имя обязательно для заполнения';
  }

  validateEmail() {
    const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    this.emailError = emailRegex.test(this.email) ? '' : 'Некорректный email';
  }

  handleSubmit(event: Event) {
    event.preventDefault();
    this.validateName();
    this.validateEmail();
    if (!this.nameError && !this.emailError) {
      // Отправить форму
    }
  }

  render() {
    return (
      <form onSub mit={(e) => this.handleSubmit(e)}>
        <label>
          Имя:
          <input
            type="text"
            value={this.name}
            onIn put={(e) => (this.name = (e.target as HTMLInputElement).value)}
            onB lur={() => this.validateName()}
          />
        </label>
        {this.nameError && <p class="error">{this.nameError}</p>}

        <label>
          Email:
          <input
            type="email"
            value={this.email}
            onIn put={(e) => (this.email = (e.target as HTMLInputElement).value)}
            onB lur={() => this.validateEmail()}
          />
        </label>
        {this.emailError && <p class="error">{this.emailError}</p>}

        <button type="submit">Отправить</button>
      </form>
    );
  }
}

Здесь форма проверяет два поля: имя и email. Каждое поле имеет свою собственную логику валидации, и все ошибки отображаются в виде сообщений рядом с полями.

Асинхронная валидация

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

Пример асинхронной валидации:

@Component({
  tag: 'async-validation-form',
  styleUrl: 'async-validation-form.css',
  shadow: true
})
export class AsyncValidationForm {
  @State() email: string = '';
  @State() emailError: string = '';

  async validateEmail() {
    const emailExists = await this.checkEmailAvailability(this.email);
    this.emailError = emailExists ? 'Этот email уже занят' : '';
  }

  async checkEmailAvailability(email: string): Promise<boolean> {
    // Эмуляция асинхронного запроса
    const existingEmails = ['test@example.com', 'user@example.com'];
    return existingEmails.includes(email);
  }

  handleSubmit(event: Event) {
    event.preventDefault();
    this.validateEmail();
    if (!this.emailError) {
      // Отправить форму
    }
  }

  render() {
    return (
      <form onSub mit={(e) => this.handleSubmit(e)}>
        <label>
          Email:
          <input
            type="email"
            value={this.email}
            onIn put={(e) => (this.email = (e.target as HTMLInputElement).value)}
            onB lur={() => this.validateEmail()}
          />
        </label>
        {this.emailError && <p class="error">{this.emailError}</p>}
        <button type="submit">Отправить</button>
      </form>
    );
  }
}

В этом примере используется асинхронная функция для проверки доступности email в базе данных (эмулированной с помощью массива). Этот подход полезен при работе с внешними API и при необходимости выполнения длительных операций.

Вывод ошибок

Важно не только выполнять валидацию, но и предоставить пользователю понятные и информативные сообщения об ошибках. В Stencil можно динамически отображать ошибки с помощью условных операторов и состояния компонентов.

{this.emailError && <p class="error">{this.emailError}</p>}

Такой подход позволяет гибко управлять отображением ошибок и делать интерфейс более дружелюбным для пользователей.

Заключение

Вали