Префиксы и суффиксы для валют

Модуль форматирования чисел в Cleave.js поддерживает отображение дополнительных текстовых элементов рядом с числовыми значениями. Наиболее распространённый сценарий — добавление валютных обозначений, единиц измерения, процентов, кодов стран и пользовательских меток.

Для этой задачи используются параметры:

  • prefix
  • noImmediatePrefix
  • rawValueTrimPrefix
  • пользовательская обработка значения через события

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


Базовый префикс валюты

Простейший пример — отображение символа валюты перед числом.

<input type="text" id="price">
new Cleave('#price', {
    numeral: true,
    numeralThousandsGroupStyle: 'thousand',
    prefix: '$'
});

Результат:

$12,500

При вводе числа библиотека автоматически:

  • добавляет символ валюты;
  • форматирует разделители тысяч;
  • сохраняет корректное положение курсора.

Префикс с пробелом

Для читаемости часто используется пробел после обозначения валюты.

new Cleave('#price', {
    numeral: true,
    prefix: '$ ',
    numeralThousandsGroupStyle: 'thousand'
});

Результат:

$ 8,900

Аналогично:

prefix: '€ '
prefix: '₸ '
prefix: 'USD '

Русские и казахстанские валютные форматы

Тенге

new Cleave('#price', {
    numeral: true,
    numeralThousandsGroupStyle: 'thousand',
    prefix: '₸ '
});

Результат:

₸ 450,000

Рубли

new Cleave('#price', {
    numeral: true,
    prefix: '₽ ',
    numeralThousandsGroupStyle: 'thousand'
});

Доллары и евро

new Cleave('#usd', {
    numeral: true,
    prefix: '$ '
});

new Cleave('#eur', {
    numeral: true,
    prefix: '€ '
});

Отключение немедленного отображения префикса

По умолчанию префикс появляется сразу после инициализации поля, даже если значение пустое.

Пример:

$

Для отключения такого поведения используется noImmediatePrefix.

new Cleave('#price', {
    numeral: true,
    prefix: '$ ',
    noImmediatePrefix: true
});

Теперь символ валюты появится только после начала ввода.


Поведение при очистке поля

Без noImmediatePrefix поле после удаления числа может выглядеть так:

$

С noImmediatePrefix: true поле полностью очищается.

Это особенно важно:

  • для placeholder;
  • при строгой UX-логике;
  • в административных интерфейсах;
  • при работе с формами фильтрации.

Получение значения без префикса

Поле отображает форматированное значение:

$ 15,000

Но во многих случаях серверу требуется:

15000

Для этого используется rawValue.

const cleave = new Cleave('#price', {
    numeral: true,
    prefix: '$ '
});

console.log(cleave.getRawValue());

Результат:

15000

Удаление префикса из rawValue

Иногда библиотека может сохранять префикс внутри raw-значения. Для принудительного удаления применяется:

rawValueTrimPrefix: true

Пример:

new Cleave('#price', {
    numeral: true,
    prefix: '$ ',
    rawValueTrimPrefix: true
});

Префиксы с кодами валют

Вместо символов нередко используются буквенные обозначения.

new Cleave('#price', {
    numeral: true,
    prefix: 'USD '
});

Результат:

USD 2,400

Другие варианты:

prefix: 'KZT '
prefix: 'EUR '
prefix: 'RUB '
prefix: 'GBP '

Динамическое изменение валюты

Префикс можно изменять во время работы приложения.

const cleave = new Cleave('#price', {
    numeral: true,
    prefix: '$ '
});

Позже:

cleave.properties.prefix = '€ ';
cleave.setRawValue('5000');

После обновления:

€ 5,000

Работа с выпадающим списком валют

Частый сценарий — переключение валюты пользователем.

<select id="currency">
    <option value="$ ">$</option>
    <option value="€ ">€</option>
    <option value="₸ ">₸</option>
</select>

<input type="text" id="amount">
const cleave = new Cleave('#amount', {
    numeral: true,
    prefix: '$ '
});

document.querySelector('#currency')
    .addEventListener('change', function () {

        cleave.properties.prefix = this.value;

        const value = cleave.getRawValue();

        cleave.setRawValue(value);
    });

Префиксы для процентов

Префикс подходит не только для валют.

new Cleave('#discount', {
    numeral: true,
    prefix: 'Discount '
});

Результат:

Discount 15

Имитация суффикса

Встроенного свойства suffix библиотека не предоставляет, поэтому суффикс реализуется вручную.

Простейший вариант:

input.addEventListener('input', function () {
    this.value = this.value + ' kg';
});

Однако такой подход конфликтует с управлением курсором.


Реализация суффикса через обработку rawValue

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

const cleave = new Cleave('#weight', {
    numeral: true
});

const input = document.querySelector('#weight');

input.addEventListener('blur', () => {
    input.value = cleave.getFormattedValue() + ' kg';
});

input.addEventListener('focus', () => {
    input.value = cleave.getRawValue();
});

Валютный суффикс после числа

Во многих странах валюта отображается после суммы.

Пример:

15 000 ₸

Такой формат можно реализовать вручную.

const cleave = new Cleave('#price', {
    numeral: true,
    numeralThousandsGroupStyle: 'thousand'
});

const input = document.querySelector('#price');

input.addEventListener('blur', () => {
    input.value = cleave.getFormattedValue() + ' ₸';
});

input.addEventListener('focus', () => {
    input.value = cleave.getRawValue();
});

Проблемы суффиксов

При ручной реализации возникают сложности:

Позиция курсора

Если суффикс находится внутри поля:

150 kg

курсор может попадать внутрь текста kg.


Удаление символов

Backspace способен удалять часть суффикса:

150 k

Повторное добавление

При повторном blur:

150 kg kg

Поэтому требуется проверка существующего суффикса.


Безопасное добавление суффикса

input.addEventListener('blur', () => {

    let value = cleave.getFormattedValue();

    if (!value.endsWith(' kg')) {
        input.value = value + ' kg';
    }
});

Использование скрытого поля

Один из лучших подходов — разделение:

  • отображаемого значения;
  • чистого значения для отправки.
<input type="text" id="visible-price">
<input type="hidden" id="real-price">
const cleave = new Cleave('#visible-price', {
    numeral: true,
    prefix: '$ '
});

document.querySelector('#visible-price')
    .addEventListener('input', () => {

        document.querySelector('#real-price').value =
            cleave.getRawValue();
    });

Комбинация префикса и десятичных знаков

new Cleave('#salary', {
    numeral: true,
    numeralDecimalScale: 2,
    prefix: '$ '
});

Результат:

$ 12,500.75

Европейские валютные форматы

new Cleave('#eur', {
    numeral: true,
    numeralDecimalMark: ',',
    delimiter: '.',
    prefix: '€ '
});

Результат:

€ 1.500,75

Использование пользовательских обозначений

Префиксы подходят для любых текстовых маркеров.

prefix: 'Сумма: '
prefix: 'Оплата: '
prefix: 'Цена: '
prefix: 'Balance: '

Пример:

new Cleave('#price', {
    numeral: true,
    prefix: 'Цена: '
});

Префиксы и React

В React префиксы работают аналогично.

<Cleave
    options={{
        numeral: true,
        prefix: '$ ',
        numeralThousandsGroupStyle: 'thousand'
    }}
/>

Получение rawValue:

onCha nge={(e) => {
    console.log(e.target.rawValue);
}}

Префиксы и Vue

<cleave
    :options="{
        numeral: true,
        prefix: '₸ '
    }"
/>

Префиксы и маски кредитных карт

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

new Cleave('#card', {
    prefix: 'CARD ',
    blocks: [4, 4, 4, 4],
    delimiter: '-'
});

Результат:

CARD 1234-5678-9012-3456

Ограничения префиксов

Префикс не является частью числа

Нельзя выполнять математические операции напрямую над:

$ 500

Необходимо использовать:

getRawValue()

Проблемы с копированием

Пользователь копирует:

$ 15,000

а не:

15000

Влияние на валидацию

Регулярные выражения должны учитывать префикс.

Неправильно:

/^\d+$/

Правильно:

/^\$\s\d+(,\d+)*$/

или проверка rawValue.


Практический пример валютного поля

<input type="text" id="salary">
const salary = new Cleave('#salary', {
    numeral: true,
    numeralThousandsGroupStyle: 'thousand',
    numeralDecimalScale: 2,
    prefix: '₸ ',
    noImmediatePrefix: true,
    rawValueTrimPrefix: true
});

Поведение:

  • отображается валюта;
  • автоматически форматируются тысячи;
  • поддерживаются дробные значения;
  • rawValue содержит только число;
  • пустое поле не показывает префикс.