Валидация в реальном времени

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

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

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

Структура компонента для валидации

Типичный компонент формы в Svelte включает в себя несколько ключевых элементов:

  1. Переменные состояния: для хранения значений формы и состояний ошибок.
  2. Реактивные выражения: для слежения за изменениями данных и вычисления ошибок.
  3. Подсказки для пользователя: для отображения ошибок в интерфейсе.

Пример простого компонента формы с валидацией:

<script>
  let email = '';
  let password = '';
  let errors = {
    email: '',
    password: ''
  };

  $: emailValid = validateEmail(email);
  $: passwordValid = validatePassword(password);

  function validateEmail(value) {
    if (!value) {
      return 'Email обязателен';
    }
    const emailRegex = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/;
    return emailRegex.test(value) ? '' : 'Неверный формат email';
  }

  function validatePassword(value) {
    if (!value) {
      return 'Пароль обязателен';
    }
    if (value.length < 6) {
      return 'Пароль должен содержать хотя бы 6 символов';
    }
    return '';
  }
</script>

<form>
  <div>
    <label for="email">Email:</label>
    <input id="email" bind:value={email} type="email" />
    {#if emailValid}
      <p class="error">{emailValid}</p>
    {/if}
  </div>

  <div>
    <label for="password">Пароль:</label>
    <input id="password" bind:value={password} type="password" />
    {#if passwordValid}
      <p class="error">{passwordValid}</p>
    {/if}
  </div>

  <button type="submit" disabled={emailValid || passwordValid}>Отправить</button>
</form>

<style>
  .error {
    color: red;
    font-size: 12px;
  }
</style>

Реактивность в валидации

Реактивность в Svelte позволяет автоматически вычислять ошибку, когда значение поля меняется. Выражение $: emailValid = validateEmail(email) будет автоматически пересчитываться каждый раз, когда меняется значение email. Это позволяет поддерживать актуальные данные о статусе валидации без необходимости вручную обновлять UI.

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

Иногда требуется проводить асинхронные проверки, например, проверку уникальности email на сервере. Для этого можно использовать промисы и async/await внутри реактивных выражений. Однако Svelte не позволяет напрямую использовать асинхронные выражения в реактивных вычислениях. Для этого можно создать отдельные методы или подписки для асинхронной валидации.

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

<script>
  let email = '';
  let emailError = '';
  let isEmailValid = false;

  async function checkEmailAvailability(value) {
    const response = await fetch(`/check-email?email=${value}`);
    const result = await response.json();
    return result.isAvailable ? '' : 'Этот email уже занят';
  }

  $: {
    if (email) {
      checkEmailAvailability(email).then(error => {
        emailError = error;
        isEmailValid = !error;
      });
    }
  }
</script>

<form>
  <div>
    <label for="email">Email:</label>
    <input id="email" bind:value={email} type="email" />
    {#if emailError}
      <p class="error">{emailError}</p>
    {/if}
  </div>
  <button type="submit" disabled={!isEmailValid}>Отправить</button>
</form>

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

Валидация при потере фокуса (blur)

Для улучшения пользовательского опыта можно внедрить валидацию, которая будет запускаться не только при каждом изменении, но и при потере фокуса (событие blur). Это позволяет предоставлять пользователю информацию о валидности данных без необходимости постоянно вводить текст.

Пример использования события blur для проверки email:

<script>
  let email = '';
  let emailError = '';

  function handleBlur() {
    emailError = validateEmail(email);
  }
</script>

<form>
  <div>
    <label for="email">Email:</label>
    <input id="email" bind:value={email} type="email" on:blur={handleBlur} />
    {#if emailError}
      <p class="error">{emailError}</p>
    {/if}
  </div>
  <button type="submit" disabled={emailError}>Отправить</button>
</form>

Подсказки и уведомления

Одной из ключевых задач при валидации является информирование пользователя о том, что именно нужно исправить. Для этого можно использовать текстовые подсказки и уведомления. В Svelte это можно сделать с помощью условных блоков ({#if}), чтобы показывать сообщения об ошибках в реальном времени.

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

Использование внешних библиотек

Хотя Svelte предоставляет удобные средства для валидации, иногда возникает потребность в использовании более сложных решений, например, при реализации валидации на стороне клиента с учётом разных типов данных. Для этого можно использовать сторонние библиотеки, такие как Yup или VeeValidate.

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

<script>
  import * as yup from 'yup';

  let email = '';
  let password = '';
  let emailError = '';
  let passwordError = '';

  const schema = yup.object().shape({
    email: yup.string().email('Неверный формат email').required('Email обязателен'),
    password: yup.string().min(6, 'Пароль должен содержать хотя бы 6 символов').required('Пароль обязателен')
  });

  $: {
    emailError = '';
    passwordError = '';
    try {
      schema.validateSync({ email, password }, { abortEarly: false });
    } catch (err) {
      err.inner.forEach(e => {
        if (e.path === 'email') emailError = e.message;
        if (e.path === 'password') passwordError = e.message;
      });
    }
  }
</script>

<form>
  <div>
    <label for="email">Email:</label>
    <input id="email" bind:value={email} type="email" />
    {#if emailError}
      <p class="error">{emailError}</p>
    {/if}
  </div>

  <div>
    <label for="password">Пароль:</label>
    <input id="password" bind:value={password} type="password" />
    {#if passwordError}
      <p class="error">{passwordError}</p>
    {/if}
  </div>

  <button type="submit" disabled={emailError || passwordError}>Отправить</button>
</form>

Итоги

Реализация валидации в реальном времени в Svelte позволяет создать удобные и интерактивные формы с минимальными усилиями. Используя реактивность и возможности фреймворка, можно быстро реагировать на изменения данных и показывать ошибки до того, как пользователь отправит форму. Это не только улучшает пользовательский опыт, но и помогает предотвращать возможные ошибки при работе с данными.