Валидация перед отправкой

Валидация перед отправкой в контексте Cleave.js строится вокруг разделения двух представлений данных: визуально отформатированного значения и «сырого» значения, пригодного для серверной обработки. Библиотека не выполняет классическую валидацию (как проверка обязательности или диапазонов), но формирует корректный ввод, снижая количество ошибок до момента сабмита.

Ключевая особенность заключается в том, что пользователь работает с форматированным вводом (карты, телефоны, даты), тогда как бизнес-логика должна опираться на очищенные данные без разделителей и масок.

Разделение formatted value и raw value

Cleave.js хранит и отображает данные в двух формах:

  • Formatted value — строка с разделителями, пробелами, дефисами
  • Raw value — чистое значение без форматирования

Для корректной отправки важно использовать именно raw value.

Основной метод получения исходного значения:

const raw = cleave.getRawValue();

Пример различий:

  • Отображение: +7 (777) 123-45-67
  • Raw: 77771234567

Именно raw используется для:

  • отправки на сервер
  • сравнения значений
  • валидации бизнес-логики

Обработка событий перед отправкой

Cleave.js предоставляет механизм отслеживания изменений через onValueChanged. Это позволяет синхронизировать состояние формы до момента submit.

const cleave = new Cleave(input, {
  phone: true,
  phoneRegionCode: 'KZ',
  onValueChanged: function (e) {
    console.log(e.target.value);     // formatted
    console.log(e.target.rawValue);  // raw
  }
});

В контексте подготовки к отправке важно хранить raw значение в состоянии формы:

let formState = {
  phone: ''
};

const cleave = new Cleave(input, {
  phone: true,
  onValueChanged: (e) => {
    formState.phone = e.target.rawValue;
  }
});

Подготовка данных формы перед submit

Перед отправкой формы необходимо исключить форматирование. Это особенно критично для:

  • телефонных номеров
  • банковских карт
  • числовых идентификаторов
  • дат

Типовой подход:

form.addEventListener('submit', (e) => {
  e.preventDefault();

  const payload = {
    phone: cleave.getRawValue()
  };

  sendToServer(payload);
});

При использовании нескольких полей Cleave.js важно централизовать сбор данных:

const payload = {
  phone: phoneCleave.getRawValue(),
  card: cardCleave.getRawValue(),
  date: dateCleave.getRawValue()
};

Валидация числовых значений после очистки

После извлечения raw value включается классическая валидация JavaScript. Cleave.js не гарантирует корректность бизнес-правил, он только нормализует ввод.

Пример проверки телефона:

const phone = cleave.getRawValue();

const isValid = phone.length === 11 && phone.startsWith('7');

Пример проверки банковской карты:

const card = cardCleave.getRawValue();

const isValid = card.length >= 13 && card.length <= 19;

Интеграция с внешними валидаторами

Cleave.js часто используется вместе с библиотеками валидации форм:

  • Yup
  • Joi
  • Validator.js
  • custom validation layers

Суть интеграции — передача raw значения в схему проверки.

Пример с условной схемой:

const schema = {
  phone: (value) => value.length === 11,
  card: (value) => value.length >= 13
};

const data = {
  phone: phoneCleave.getRawValue(),
  card: cardCleave.getRawValue()
};

const isValid = Object.keys(schema).every((key) => {
  return schema[key](data[key]);
});

Синхронизация состояния формы

В современных интерфейсах важно поддерживать единое состояние между DOM и моделью данных. Cleave.js выступает как слой форматирования, но не как источник истины.

Типовая архитектура:

  1. Пользователь вводит данные
  2. Cleave.js форматирует отображение
  3. onValueChanged обновляет state
  4. submit использует state.raw values

Пример:

const state = {
  phone: '',
  card: ''
};

const phoneCleave = new Cleave('#phone', {
  phone: true,
  onValueChanged: (e) => {
    state.phone = e.target.rawValue;
  }
});

const cardCleave = new Cleave('#card', {
  creditCard: true,
  onValueChanged: (e) => {
    state.card = e.target.rawValue;
  }
});

Очистка данных при потере фокуса

В некоторых сценариях требуется дополнительная проверка при blur. Это позволяет отсеивать неполные значения до отправки формы.

input.addEventListener('blur', () => {
  const value = cleave.getRawValue();

  if (value.length === 0) {
    input.classList.add('error');
  }
});

Такой подход часто используется в сочетании с визуальной индикацией ошибок.

Защита от отправки форматированных значений

Частая ошибка — отправка input.value вместо getRawValue(). Это приводит к необходимости серверной очистки данных.

Антипаттерн:

const payload = {
  phone: input.value // ❌ содержит маску
};

Корректный вариант:

const payload = {
  phone: cleave.getRawValue() // ✔ чистое значение
};

Работа с частично введёнными значениями

Cleave.js допускает неполный ввод, что требует дополнительной логики перед отправкой.

Пример проверки заполненности:

function isCompletePhone(cleaveInstance) {
  return cleaveInstance.getRawValue().length === 11;
}

Использование перед submit:

if (!isCompletePhone(phoneCleave)) {
  return;
}

Валидация сложных форматов

Для сложных масок (например, даты или серийные номера) важно учитывать порядок ввода.

Пример даты:

const date = dateCleave.getRawValue();

const isValidDate = /^\d{8}$/.test(date);

Здесь Cleave.js обеспечивает формат DD/MM/YYYY, но проверка корректности остаётся за приложением.

Объединение форматирования и бизнес-логики

Правильная архитектура разделяет:

  • Cleave.js → форматирование ввода
  • JavaScript → извлечение raw данных
  • Validator → проверка правил
  • API слой → отправка

Такой подход предотвращает смешение обязанностей и упрощает поддержку кода.

function preparePayload() {
  return {
    phone: phoneCleave.getRawValue(),
    card: cardCleave.getRawValue(),
    date: dateCleave.getRawValue()
  };
}

Контроль состояния перед отправкой

Перед финальным submit полезно централизовать контроль:

function canSubmit() {
  return (
    phoneCleave.getRawValue().length === 11 &&
    cardCleave.getRawValue().length >= 13
  );
}

И использование:

form.addEventListener('submit', (e) => {
  e.preventDefault();

  if (!canSubmit()) return;

  sendToServer(preparePayload());
});

Обработка ошибок ввода после форматирования

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

Типичный сценарий:

  • пользователь вводит «почти корректный» номер
  • Cleave.js отображает формат
  • raw value остаётся неполным
  • submit блокируется логикой валидации

Пример:

const raw = phoneCleave.getRawValue();

if (!/^\d{11}$/.test(raw)) {
  showError('Неверный номер');
}

Использование Cleave.js как слоя нормализации данных

В сложных формах Cleave.js выполняет роль промежуточного слоя:

  • унифицирует ввод
  • снижает количество пользовательских ошибок
  • упрощает клиентскую валидацию
  • обеспечивает стабильный raw output для серверной логики

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