Библиотека Cleave.js предоставляет инструменты для форматирования пользовательского ввода, однако контроль диапазона допустимых значений требует дополнительной логики. Особенно это важно при работе с числовыми полями, денежными суммами, процентами, временем, возрастом, количеством товаров, рейтингами и любыми другими данными, имеющими минимальные и максимальные ограничения.
Cleave.js отвечает прежде всего за:
Проверка диапазона значений не входит в базовый функционал библиотеки. Например:
new Cleave('.input', {
numeral: true
});
Такое поле позволит вводить:
1
100
999999999
-5000
Даже если логически допустим только диапазон от 1 до
100.
Поэтому ограничение диапазона реализуется вручную через:
onValueChanged;input;Наиболее распространённый сценарий — ограничение числового диапазона.
<input type="text" class="quantity">
const cleave = new Cleave('.quantity', {
numeral: true,
numeralIntegerScale: 3,
onValueChanged: function(event) {
let value = parseInt(event.target.rawValue || 0);
if (value < 1) {
value = 1;
}
if (value > 100) {
value = 100;
}
event.target.value = value;
}
});
rawValue содержит неформатированное значение:
event.target.rawValue
Если пользователь вводит:
150
логика автоматически изменит значение:
100
Прямое изменение event.target.value не всегда
синхронизируется с внутренним состоянием Cleave.js. Более корректным
вариантом считается использование метода setRawValue.
const cleave = new Cleave('.quantity', {
numeral: true,
onValueChanged: function(event) {
let value = Number(event.target.rawValue);
if (value > 5000) {
cleave.setRawValue(5000);
}
}
});
Метод:
Во многих интерфейсах отрицательные числа недопустимы.
new Cleave('.price', {
numeral: true,
numeralPositiveOnly: true
});
Опция автоматически:
-;Иногда диапазон задаётся не числовыми пределами, а количеством цифр.
new Cleave('.code', {
numeral: true,
numeralIntegerScale: 4
});
Если указано:
numeralIntegerScale: 4
то пользователь сможет ввести максимум:
9999
Попытка ввода пятой цифры будет проигнорирована.
Для финансовых данных требуется строгий контроль количества знаков после запятой.
new Cleave('.money', {
numeral: true,
numeralDecimalScale: 2
});
Допустимые значения:
10
10.5
10.55
Недопустимо:
10.555
Процентные значения обычно находятся в диапазоне:
0–100
<input type="text" class="percent">
const percent = new Cleave('.percent', {
numeral: true,
numeralPositiveOnly: true,
numeralDecimalScale: 2,
onValueChanged: function(event) {
let value = parseFloat(event.target.rawValue);
if (isNaN(value)) {
return;
}
if (value > 100) {
percent.setRawValue(100);
}
}
});
0
45
99.99
100
Существует два подхода к ограничению диапазона.
Значение немедленно исправляется:
if (value > 100) {
cleave.setRawValue(100);
}
Пользователь может ввести любое значение, но интерфейс показывает ошибку.
if (value > 100) {
input.classList.add('error');
}
Подходит для:
Используется в:
Cleave.js умеет форматировать даты, но не валидирует их диапазон автоматически.
new Cleave('.date', {
date: true,
datePattern: ['d', 'm', 'Y']
});
Такое поле позволит вводить:
99/99/9999
если не реализовать дополнительную проверку.
const input = document.querySelector('.date');
new Cleave(input, {
date: true,
datePattern: ['d', 'm', 'Y']
});
input.addEventListener('blur', () => {
const parts = input.value.split('/');
if (parts.length !== 3) {
return;
}
const date = new Date(
parts[2],
parts[1] - 1,
parts[0]
);
const min = new Date(2020, 0, 1);
const max = new Date(2030, 11, 31);
if (date < min || date > max) {
alert('Дата вне диапазона');
}
});
Временные интервалы также требуют дополнительной проверки.
new Cleave('.time', {
time: true,
timePattern: ['h', 'm']
});
input.addEventListener('blur', () => {
const [hours, minutes] = input.value.split(':').map(Number);
const total = hours * 60 + minutes;
const min = 9 * 60;
const max = 18 * 60;
if (total < min || total > max) {
alert('Недопустимое время');
}
});
При использовании input type="number" доступны
встроенные ограничения HTML.
<input
type="number"
min="1"
max="10"
>
Однако при использовании Cleave.js обычно применяется:
<input type="text">
Поэтому атрибуты:
min
max
не работают автоматически.
Диапазонные ограничения часто сопровождаются отображением ошибок.
.invalid {
border-color: red;
}
if (value < 1 || value > 100) {
input.classList.add('invalid');
} else {
input.classList.remove('invalid');
}
Проверка может происходить:
onValueChanged: function(event) {
let value = Number(event.target.rawValue);
if (value > 999) {
cleave.setRawValue(999);
}
}
input.addEventListener('blur', validate);
form.addEventListener('submit', validate);
Постоянная проверка диапазона может создавать лишнюю нагрузку.
function debounce(fn, delay) {
let timeout;
return function() {
clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
input.addEventListener('input', debounce(() => {
validateRange();
}, 300));
Финансовые поля особенно часто требуют диапазонного контроля.
const salary = new Cleave('.salary', {
numeral: true,
prefix: '$ ',
numeralThousandsGroupStyle: 'thousand',
onValueChanged: function(event) {
let value = Number(event.target.rawValue);
if (value > 1000000) {
salary.setRawValue(1000000);
}
}
});
Часто используются:
import Cleave from 'cleave.js/react';
import { useState } from 'react';
function AmountInput() {
const [value, setValue] = useState('');
const handleChange = (e) => {
let raw = Number(e.target.rawValue);
if (raw > 1000) {
raw = 1000;
}
setValue(raw);
};
return (
<Cleave
value={value}
options={{
numeral: true
}}
onCha nge={handleChange}
/>
);
}
methods: {
onInput(event) {
let value = Number(event.target.rawValue);
if (value > 500) {
value = 500;
}
this.amount = value;
}
}
На практике диапазон редко ограничивается одним условием.
new Cleave('.input', {
numeral: true,
numeralPositiveOnly: true,
numeralIntegerScale: 5,
numeralDecimalScale: 2
});
Неправильно:
Number(event.target.value)
Правильно:
Number(event.target.rawValue)
Ошибка:
parseInt('10.99')
Результат:
10
Для дробных чисел необходимо:
parseFloat()
или:
Number()
Неправильная логика может вызывать рекурсивное обновление.
Проблемный код:
onValueChanged: function(event) {
cleave.setRawValue(event.target.rawValue);
}
18–99
1–1000
0–100
1–5
0–5000000
09:00–18:00
01.01.2025–31.12.2025