Валидация перед переходом

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

Использование beforeShowPromise для асинхронной проверки

Каждый шаг тура в Shepherd.js поддерживает опцию beforeShowPromise, которая позволяет выполнить асинхронную проверку перед отображением шага. Если промис отклоняется, шаг не будет показан. Это удобно для случаев, когда необходимо убедиться, что пользователь выполнил определённое действие на предыдущем шаге.

Пример:

const tour = new Shepherd.Tour({
  defaultStepOptions: {
    cancelIcon: { enabled: true },
    classes: 'shepherd-theme-arrows',
    scrollTo: { beh * avior: 'smooth', block: 'center' }
  }
});

tour.addStep({
  id: 'step-1',
  text: 'Введите ваше имя в поле ниже',
  attachTo: { element: '#name-input', on: 'bottom' },
  buttons: [
    {
      text: 'Далее',
      action: tour.next
    }
  ],
  beforeShowPromise: () => {
    return new Promise((resolve, reject) => {
      const input = document.querySelector('#name-input');
      if (input.value.trim() !== '') {
        resolve();
      } else {
        alert('Пожалуйста, заполните поле имени');
        reject();
      }
    });
  }
});

tour.start();

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

Валидация на уровне кнопок с использованием action

Кроме глобальной проверки перед отображением шага, можно валидацию осуществлять непосредственно при нажатии кнопок. Для этого в опции buttons используется метод action, который может содержать функцию с проверкой:

tour.addStep({
  id: 'step-2',
  text: 'Подтвердите согласие с условиями',
  attachTo: { element: '#terms-checkbox', on: 'right' },
  buttons: [
    {
      text: 'Далее',
      action: function() {
        const checkbox = document.querySelector('#terms-checkbox');
        if (checkbox.checked) {
          tour.next();
        } else {
          alert('Необходимо принять условия');
        }
      }
    }
  ]
});

Такой подход позволяет гибко контролировать переход, не блокируя весь тур и при этом обеспечивая интерактивность.

Динамическое управление шагами через canClickNext

Для упрощения логики валидации можно использовать кастомный флаг на шаге, например canClickNext. В обработчиках событий полей формы устанавливается этот флаг, а кнопка “Далее” проверяет его значение перед вызовом tour.next().

let canClickNext = false;

document.querySelector('#email-input').addEventListener('input', (e) => {
  canClickNext = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e.target.value);
});

tour.addStep({
  id: 'step-3',
  text: 'Введите ваш email',
  attachTo: { element: '#email-input', on: 'top' },
  buttons: [
    {
      text: 'Далее',
      action: function() {
        if (canClickNext) {
          tour.next();
        } else {
          alert('Введите корректный email');
        }
      }
    }
  ]
});

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

Асинхронная проверка через API

Shepherd.js позволяет интегрировать запросы к серверу перед переходом. Например, проверка доступности имени пользователя:

tour.addStep({
  id: 'step-username',
  text: 'Проверьте доступность имени пользователя',
  attachTo: { element: '#username-input', on: 'bottom' },
  buttons: [
    {
      text: 'Далее',
      action: function() {
        const username = document.querySelector('#username-input').value;
        fetch(`/api/check-username?username=${username}`)
          .then(res => res.json())
          .then(data => {
            if (data.available) {
              tour.next();
            } else {
              alert('Имя пользователя занято');
            }
          })
          .catch(() => alert('Ошибка проверки имени'));
      }
    }
  ]
});

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

Совмещение нескольких условий

Часто требуется проверять сразу несколько условий перед переходом. Для этого можно использовать комбинацию beforeShowPromise и кастомных кнопок:

tour.addStep({
  id: 'step-multi',
  text: 'Заполните форму полностью и подтвердите условия',
  attachTo: { element: '#form-section', on: 'left' },
  buttons: [
    {
      text: 'Далее',
      action: function() {
        const inputFilled = document.querySelector('#form-input').value.trim() !== '';
        const termsChecked = document.querySelector('#terms').checked;
        if (inputFilled && termsChecked) {
          tour.next();
        } else {
          alert('Все поля должны быть заполнены и условия приняты');
        }
      }
    }
  ]
});

Такой подход обеспечивает гибкость и читаемость кода, позволяя комбинировать синхронные и асинхронные проверки.

Выводы по валидации

  • beforeShowPromise – для асинхронной проверки перед отображением шага.
  • Проверка на кнопках через action – для интерактивного контроля перехода.
  • Использование флагов и реактивных событий – для динамической валидации форм.
  • Интеграция с API – для серверной валидации данных.
  • Комбинирование методов – для сложных сценариев с несколькими условиями.

Эти методы обеспечивают полный контроль над поведением тура и позволяют создавать надежные и интерактивные пользовательские сценарии с минимальными усилиями.