Cleave.js реализует форматирование ввода через конфигурацию, которая задаёт «режим» обработки значения поля. Под режимом ввода в данном контексте понимается набор правил преобразования строки: телефон, дата, числовые значения, кредитные карты или произвольные маски. Переключение между такими режимами означает изменение логики разбиения, вставки разделителей и нормализации вводимого значения без разрушения UX-потока.
Каждый экземпляр библиотеки представляет собой слой над input-элементом и хранит:
options);Режим ввода определяется набором опций:
numeral — числовой режим;date — работа с датами;phone — телефонные номера;creditCard — банковские карты;blocks + delimiter — кастомные маски;prefix / numeralDecimalMark /
numeralIntegerScale — числовая кастомизация.Смена режима — это фактически смена конфигурации интерпретации строки, а не просто форматирование вывода.
После инициализации Cleave.js не предполагает «переключение типа» как статическую операцию. Внутренний процесс привязан к текущим правилам парсинга, поэтому изменение режима требует либо обновления состояния, либо пересоздания экземпляра.
Ключевой момент: форматирование выполняется на основе текущих
properties, и они не всегда полностью реактивны.
Наиболее предсказуемый способ смены режима — уничтожение текущего экземпляра и создание нового.
let cleaveInstance = new Cleave(input, {
numeral: true,
numeralThousandsGroupStyle: 'thousand'
});
function switchToDateMode() {
cleaveInstance.destroy();
cleaveInstance = new Cleave(input, {
date: true,
datePattern: ['d', 'm', 'Y']
});
}
Особенности подхода:
Для сохранения данных используется извлечение raw-значения до уничтожения:
const raw = cleaveInstance.getRawValue();
cleaveInstance.destroy();
После пересоздания значение может быть повторно применено:
cleaveInstance = new Cleave(input, config);
cleaveInstance.setRawValue(raw);
Некоторые конфигурации допускают частичную модификацию без пересоздания. Это зависит от конкретной версии и набора опций.
Пример изменения числовых параметров:
cleaveInstance.properties.numeralThousandsGroupStyle = 'lakh';
cleaveInstance.properties.numeralDecimalScale = 3;
Однако подобный подход имеет ограничения:
Типичный приём:
const raw = cleaveInstance.getRawValue();
cleaveInstance.properties.numeral = true;
cleaveInstance.properties.date = false;
cleaveInstance.setRawValue(raw);
Недостаток подхода — непредсказуемость при смене несовместимых
режимов (например, date → phone).
Практически применяемая архитектура — хранение набора конфигураций и их подстановка.
const configs = {
phone: {
phone: true,
phoneRegionCode: 'KZ'
},
date: {
date: true,
datePattern: ['d', 'm', 'Y']
},
numeral: {
numeral: true,
numeralThousandsGroupStyle: 'thousand'
}
};
Смена режима:
function applyMode(mode) {
const raw = cleaveInstance.getRawValue();
cleaveInstance.destroy();
cleaveInstance = new Cleave(input, configs[mode]);
cleaveInstance.setRawValue(raw);
}
Данный подход стабилизирует поведение при переходе между несовместимыми режимами и снижает риск артефактов форматирования.
При смене режима важно учитывать различие форматов:
Поэтому перенос значения часто требует промежуточной нормализации:
const rawValue = cleaveInstance.getRawValue();
function normalize(value, fromMode, toMode) {
if (fromMode === 'phone' && toMode === 'numeral') {
return value.replace(/\D/g, '');
}
if (fromMode === 'date') {
return value.replace(/\D/g, '');
}
return value;
}
Одной из сложностей является потеря позиции каретки. Cleave.js пересчитывает курсор на основе форматирования, и при пересоздании экземпляра это состояние теряется.
Типовой механизм компенсации:
const selectionStart = input.selectionStart;
applyMode('date');
requestAnimationFrame(() => {
input.setSelectionRange(selectionStart, selectionStart);
});
Однако корректность зависит от длины нового форматированного значения.
В UI, где режим зависит от состояния (например, выбор типа ввода), применяется декларативная модель:
let mode = 'phone';
function setMode(nextMode) {
mode = nextMode;
applyMode(mode);
}
При каждом изменении режима экземпляр пересоздаётся, а конфигурация берётся из централизованного источника.
При переключении режимов важно разделять:
Используемая модель:
function getState() {
return {
formatted: input.value,
raw: cleaveInstance.getRawValue()
};
}
При переключении режимов источником истины остаётся raw-значение.
Для близких режимов возможно частичное обновление без destroy:
cleaveInstance.properties.prefix = '+7';
cleaveInstance.properties.delimiter = '-';
cleaveInstance.setRawValue(cleaveInstance.getRawValue());
Подходит для вариаций одного типа маски, но не для смены класса данных (например, число → дата).
При переключении необходимо учитывать:
date не интерпретирует
телефонные символы);На практике используется трёхуровневая схема:
class InputModeManager {
constructor(input) {
this.input = input;
this.instance = null;
}
setMode(config) {
const raw = this.instance ? this.instance.getRawValue() : '';
if (this.instance) {
this.instance.destroy();
}
this.instance = new Cleave(this.input, config);
this.instance.setRawValue(raw);
}
}
Переключение режимов в Cleave.js сводится к управлению жизненным циклом экземпляра и миграции данных между несовместимыми схемами форматирования. Основная сложность заключается не в самом переключении, а в сохранении семантики данных при смене правил интерпретации ввода.