Динамическое изменение опций форматирования

В Cleave.js поведение форматирования определяется набором опций, передаваемых при создании экземпляра. Эти опции формируют внутреннюю конфигурацию properties, на основе которой происходит парсинг и переформатирование ввода. В классическом сценарии библиотека рассматривается как «инициализируемый один раз объект», однако реальные интерфейсы требуют изменения правил форматирования уже после создания экземпляра.

Динамическое изменение опций в Cleave.js не является единым встроенным механизмом. Вместо этого используется комбинация пересоздания экземпляра, модификации внутренних свойств и повторного применения текущего значения.


Базовая модель конфигурации

При создании экземпляра:

const cleave = new Cleave(input, {
  numeral: true,
  numeralThousandsGroupStyle: 'thousand',
  prefix: '$'
});

формируется объект:

  • cleave.properties — активная конфигурация
  • cleave.init() — инициализация поведения
  • cleave.onInput() — обработка каждого изменения значения

Вся логика форматирования опирается на properties, поэтому любые изменения опций должны либо:

  • обновить properties
  • либо пересоздать экземпляр

Подход 1. Пересоздание экземпляра

Наиболее стабильный и предсказуемый способ изменения конфигурации — полное уничтожение текущего экземпляра и создание нового.

Уничтожение текущего состояния

cleave.destroy();

После вызова:

  • удаляются обработчики событий
  • очищаются внутренние ссылки
  • форматирование прекращается

Создание нового экземпляра

const newCleave = new Cleave(input, {
  numeral: true,
  numeralThousandsGroupStyle: 'lakh',
  prefix: '₹'
});

Особенности подхода

  • гарантированно применяются новые правила форматирования
  • исключаются побочные эффекты старой конфигурации
  • теряется внутреннее состояние обработки ввода (каретка, частично введённые данные)

Подход 2. Изменение properties без пересоздания

Внутренняя структура Cleave.js допускает прямую модификацию объекта properties. Этот подход используется при необходимости сохранить текущее значение и состояние поля.

Пример изменения конфигурации

cleave.properties.prefix = '€';
cleave.properties.numeralThousandsGroupStyle = 'thousand';

После изменения требуется принудительное обновление отображения:

cleave.setRawValue(cleave.getRawValue());

Механизм обновления

  • getRawValue() возвращает неформатированное значение
  • setRawValue() повторно прогоняет значение через новый набор правил
  • происходит перерасчёт форматирования без пересоздания DOM-слушателей

Ограничения

  • не все поля конфигурации реагируют на динамическое изменение
  • сложные типы масок (blocks, delimiters, prefix behavior) могут требовать повторной инициализации
  • возможны расхождения между UI и внутренним состоянием при частых изменениях

Подход 3. Обновление числового режима (numeral)

Наиболее стабильной зоной динамического изменения является числовое форматирование.

Изменение стиля группировки

cleave.properties.numeralThousandsGroupStyle = 'thousand';
cleave.setRawValue(cleave.getRawValue());

Поддерживаемые варианты:

  • thousand
  • lakh
  • wan

Изменение префикса

cleave.properties.prefix = '$';
cleave.setRawValue(cleave.getRawValue());

При этом префикс пересчитывается при каждом рендере значения.


Подход 4. Динамическое изменение масок (blocks и delimiters)

Для шаблонных масок (например, телефонные номера или коды) используется структура:

{
  blocks: [3, 3, 4],
  delimiters: ['-', '-']
}

Пример изменения структуры

cleave.properties.blocks = [2, 2, 2, 2];
cleave.properties.delimiters = [' ', ' ', ' '];
cleave.setRawValue(cleave.getRawValue());

Поведение после изменения

  • перерасчёт групп символов
  • перераспределение уже введённых данных
  • возможное смещение курсора

Подход 5. Переключение режимов форматирования

В ряде интерфейсов требуется переключение между режимами:

  • числовой ввод
  • телефонная маска
  • кредитная карта
  • пользовательский формат

Переключение через пересоздание

cleave.destroy();

cleave = new Cleave(input, {
  phone: true,
  phoneRegionCode: 'US'
});

Переключение через модификацию свойств

cleave.properties.phone = true;
cleave.properties.numeral = false;
cleave.properties.blocks = null;
cleave.properties.delimiters = null;

cleave.setRawValue(cleave.getRawValue());

Пересоздание обеспечивает более стабильное поведение при смене режима.


Управление значением при изменении опций

Любое динамическое изменение конфигурации требует сохранения текущего состояния ввода.

Получение текущего значения

const raw = cleave.getRawValue();
const formatted = cleave.getFormattedValue();

Восстановление после смены опций

cleave.setRawValue(raw);

Использование setValue() применяется реже, так как оно повторно запускает полную цепочку обработки DOM-ввода.


Особенности работы с кареткой

Одним из сложных аспектов динамического изменения является позиция курсора.

При изменении опций:

  • длина форматированной строки изменяется
  • появляются/исчезают разделители
  • смещается индекс ввода

Cleave.js автоматически пытается сохранить позицию, однако при изменении структуры маски точность сохранения снижается.

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

const pos = input.selectionStart;

cleave.properties.delimiters = ['-', '-', '-'];
cleave.setRawValue(cleave.getRawValue());

input.setSelectionRange(pos, pos);

Обновление опций в UI-фреймворках

В обёртках для React и Vue динамическое изменение опций часто реализуется декларативно.

React-подход

<Cleave
  value={value}
  options={{
    numeral: true,
    prefix: currency
  }}
/>

При изменении currency:

  • компонент пересоздаёт внутренний Cleave-инстанс
  • старые настройки уничтожаются
  • новое состояние инициализируется автоматически

Поведение

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

Частые ошибки при динамическом изменении

Мутация без перерендера

Изменение:

cleave.properties.prefix = '€';

без последующего:

cleave.setRawValue(...)

приводит к рассинхронизации отображения.


Попытка частичного изменения маски

Изменение только blocks без delimiters часто даёт неконсистентный результат, так как оба параметра взаимосвязаны.


Смешивание режимов

Одновременное включение:

numeral: true
phone: true

создаёт конфликт поведения форматирования. При динамическом переключении требуется явное отключение предыдущего режима.


Рекомендованная стратегия управления конфигурацией

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

  1. Полное пересоздание экземпляра при смене режима ввода
  2. Модификация properties + setRawValue() при точечных изменениях (prefix, group style)

Гибридный подход позволяет разделять:

  • структурные изменения (маска, режим)
  • косметические изменения (разделители, формат чисел)