Библиотека Cleave.js не является инструментом валидации в строгом смысле. Её основная задача — форматирование пользовательского ввода в реальном времени: добавление разделителей, группировка цифр, маскировка структуры значений (телефоны, даты, кредитные карты, числовые значения).
Ключевой принцип при работе с ней в системах валидации:
форматирование и валидация должны быть разделены
Cleave.js хранит два состояния:
Для валидации критически важно использовать именно raw value.
Пример получения:
const cleave = new Cleave(input, {
phone: true,
phoneRegionCode: 'KZ'
});
// получение "сырого" значения
const raw = cleave.getRawValue();
Использование formatted value в валидации приводит к проблемам:
Клиентская валидация должна строиться в два этапа:
Cleave.js предоставляет событие изменения:
const cleave = new Cleave(input, {
numeral: true,
onValueChanged: function (e) {
const rawValue = e.target.rawValue;
validate(rawValue);
}
});
В этом контексте:
e.target.value — форматированное значениеe.target.rawValue — значение для логикиHTML5 constraints работают только с итоговым значением поля, поэтому требуется синхронизация:
input.addEventListener('input', () => {
input.setCustomValidity('');
});
Однако при использовании Cleave.js важно помнить:
pattern могут конфликтовать с
форматированиемfunction validatePhone(raw) {
return /^\d{10,15}$/.test(raw);
}
const cleave = new Cleave(input, {
phone: true,
onValueChanged: function (e) {
const raw = e.target.rawValue;
if (!validatePhone(raw)) {
input.setCustomValidity('Неверный номер телефона');
} else {
input.setCustomValidity('');
}
}
});
Клиентская валидация в любой системе считается вспомогательной. Основной контроль всегда выполняется на сервере.
Сервер никогда не должен доверять форматированным данным, даже если они прошли Cleave.js.
Перед валидацией данные приводятся к каноническому виду:
Пример:
function normalizePhone(value) {
return value.replace(/\D/g, '');
}
function isValidPhone(raw) {
const normalized = normalizePhone(raw);
return normalized.length >= 10 && normalized.length <= 15;
}
При работе с Cleave.js часто используется маска для карточек:
const cleave = new Cleave(input, {
creditCard: true
});
На сервере обязательно выполняется проверка:
function luhnCheck(number) {
let sum = 0;
let double = false;
for (let i = number.length - 1; i >= 0; i--) {
let digit = parseInt(number[i], 10);
if (double) {
digit *= 2;
if (digit > 9) digit -= 9;
}
sum += digit;
double = !double;
}
return sum % 10 === 0;
}
Ключевая проблема интеграции Cleave.js — различие между форматами данных.
Передавать следует:
Пример:
{
"phone_raw": "77001234567",
"phone_formatted": "+7 (700) 123-45-67"
}
Оптимально:
phone_rawОсобенности:
Cleave.js обеспечивает визуальную структуру, но не проверяет:
Поэтому серверная логика обязательна.
Cleave.js может форматировать даты:
new Cleave(input, {
date: true,
datePattern: ['Y', 'm', 'd']
});
Но валидация должна учитывать:
Пример серверной проверки:
function isValidDate(y, m, d) {
const date = new Date(y, m - 1, d);
return date.getFullYear() === y &&
date.getMonth() === m - 1 &&
date.getDate() === d;
}
Cleave.js поддерживает форматирование чисел:
Но сервер должен:
function parseNumber(value) {
return Number(value.replace(/,/g, ''));
}
Проблема:
Cleave.js не предназначен для:
Если клиент и сервер используют разные правила очистки:
Корректная схема интеграции выглядит так:
function normalize(input, type) {
switch (type) {
case 'phone':
return input.replace(/\D/g, '');
case 'number':
return input.replace(/,/g, '');
case 'date':
return input;
default:
return input.trim();
}
}
Важно, чтобы все поля имели:
При использовании Cleave.js возможны ситуации:
Поэтому валидация должна учитывать: