useFormatter

Composable, возвращающий общие экземпляры FormatterNumbers и FormatterIban, преднастроенные спецификациями стран.

Обзор

useFormatter() — это composable, экспортируемый из @bitrix24/b24jssdk. Он возвращает два общих форматтера-синглтона:

  • formatterNumber — экземпляр FormatterNumbers, обёртка над Intl.NumberFormat с учётом локали.
  • formatterIban — экземпляр FormatterIban, предзагруженный спецификациями стран IBAN: каждая страна из официального реестра IBAN, несколько неофициальных стран, следующих структуре IBAN, и французские региональные / административные территориальные единицы (GF, GP, MQ, RE, PF, TF, YT, NC, BL, MF, PM).

Оба форматтера — синглтоны (FormatterNumbers.getInstance() / FormatterIban.getInstance()), поэтому каждый вызов useFormatter() возвращает одни и те же нижележащие экземпляры — состояние, заданное на одном (например, локаль по умолчанию), видно везде в приложении. useFormatter() перерегистрирует спецификации IBAN при каждом вызове, но поскольку formatterIban — синглтон, а addSpecification просто перезаписывает запись в map для кода страны, повторный вызов useFormatter() дёшев.

import { useFormatter } from '@bitrix24/b24jssdk'

const { formatterNumber, formatterIban } = useFormatter()

console.log(formatterIban.printFormat('GB29NWBK60161331926819'))
// 'GB29 NWBK 6016 1331 9268 19'

console.log(formatterIban.isValid('DE89370400440532013000'))
// true

console.log(formatterNumber.format(1234.567))
// '1,234.57'

Сигнатура методов

useFormatter()

useFormatter(): {
  formatterNumber: FormatterNumbers
  formatterIban: FormatterIban
}

FormatterNumbers

setDefLocale(locale: string): void
format(value: number, locale?: string): string

FormatterIban

addSpecification(spec: IbanSpecification): void

isValid(iban: string): boolean
printFormat(iban: string, separator?: string): string     // разделитель по умолчанию ' '
electronicFormat(iban: string): string                     // убирает не-буквенно-цифровые символы, переводит в верхний регистр

toBBAN(iban: string, separator?: string): string           // разделитель по умолчанию ' '
fromBBAN(countryCode: string, bban: string): string
isValidBBAN(countryCode: string, bban: string): boolean

Ключевые понятия

FormatterNumbers.format выбирает локаль в таком порядке: явный аргумент locale, затем локаль, заданная через setDefLocale, затем navigator.language (только в браузере), затем откат к 'en'. Целые числа форматируются с 0 знаками после запятой, нецелые — ровно с 2. Когда разрешённая локаль содержит 'ru', десятичная запятая, производимая Intl.NumberFormat, заменяется на точку.
FormatterIban.isValid и методы BBAN (toBBAN, fromBBAN, isValidBBAN) выбрасывают Error('No country with code XX'), если у кода страны IBAN/BBAN нет зарегистрированной IbanSpecification. Поскольку useFormatter() уже регистрирует каждую поддерживаемую страну, это случается только для действительно неподдерживаемых или некорректных кодов стран.
  • isValid принимает слабо форматированный ввод. Сначала он прогоняет IBAN через electronicFormat, поэтому пробелы и буквы в нижнем регистре нормализуются до проверки специфичных для страны длины, структуры и контрольной суммы ISO 7064 MOD 97-10. Не-строковый ввод возвращает false вместо выброса исключения.
  • printFormat и toBBAN оба сначала нормализуют через electronicFormat, поэтому принимают тот же слабо форматированный ввод, что и isValid.
  • addSpecification перезаписывает по коду страны. Повторный вызов для уже зарегистрированной страны (как делает useFormatter() при каждом вызове) просто заменяет существующую IbanSpecification — он не накопительный и не может выбросить исключение.
  • FormatterNumbers и FormatterIban нельзя сконструировать напрямую. Оба класса защищают свой конструктор, и только getInstance() может создать синглтон; всегда получайте их через useFormatter().

Обработка ошибок

useFormatter() сам по себе никогда не выбрасывает исключений. FormatterIban.isValid возвращает false для некорректного или не-строкового ввода вместо выброса. Хелперы BBAN (toBBAN, fromBBAN, isValidBBAN) и путь проверки контрольной суммы выбрасывают Error('No country with code XX') только для кода страны без зарегистрированной IbanSpecification — чего useFormatter() никогда не производит, так как регистрирует каждую поддерживаемую страну при каждом вызове. FormatterNumbers делегирует Intl.NumberFormat, который выбрасывает RangeError для недопустимой локали или опции, но не для числового ввода.

Примеры

Валидация и форматирование IBAN:

import { useFormatter } from '@bitrix24/b24jssdk'

const { formatterIban } = useFormatter()

formatterIban.isValid('DE89370400440532013000') // true
formatterIban.isValid('GB29NWBK60161331926818') // false (неверная контрольная сумма)

formatterIban.printFormat('GB29NWBK60161331926819') // 'GB29 NWBK 6016 1331 9268 19'
formatterIban.printFormat('GB29NWBK60161331926819', '-') // 'GB29-NWBK-6016-1331-9268-19'

// Принимает слабо форматированный ввод (пробелы, нижний регистр)
formatterIban.electronicFormat('GB29 NWBK 6016 1331 9268 19') // 'GB29NWBK60161331926819'

Конвертация между IBAN и BBAN:

import { useFormatter } from '@bitrix24/b24jssdk'

const { formatterIban } = useFormatter()

formatterIban.toBBAN('GB29NWBK60161331926819') // 'NWBK 601613 31926819'
formatterIban.toBBAN('GB29NWBK60161331926819', '-') // 'NWBK-601613-31926819'

formatterIban.isValidBBAN('GB', 'NWBK60161331926819') // true
formatterIban.fromBBAN('GB', 'NWBK60161331926819') // 'GB29NWBK60161331926819'

Форматирование чисел с учётом локали:

import { useFormatter } from '@bitrix24/b24jssdk'

const { formatterNumber } = useFormatter()

formatterNumber.format(1234) // '1,234' (целое, 'en' по умолчанию)
formatterNumber.format(1234.567) // '1,234.57' (округлено до 2 знаков)
formatterNumber.format(1234.5, 'de') // '1.234,50'

formatterNumber.setDefLocale('ru')
formatterNumber.format(1234.5) // '1 234.50' (ru-группировка, точка сохранена вместо запятой)

Альтернативы и рекомендации

  • Используйте formatterIban.isValid для проверки пользовательского ввода перед вызовом printFormat/toBBAN. Оба метода форматирования только нормализуют строку — они не проверяют контрольную сумму, поэтому некорректный IBAN всё равно можно «напечатать» или сконвертировать.
  • Вызывайте useFormatter() один раз на модуль/компонент и деструктурируйте то, что нужно. Поскольку оба форматтера — синглтоны, нет смысла кэшировать возвращаемый объект самому, кроме как ради избавления от boilerplate деструктуризации.
  • Для обычного форматирования тысяч/десятичных без учёта локали предпочитайте Text.numberFormat. formatterNumber.format учитывает локаль (через Intl.NumberFormat) и всегда округляет нецелые до ровно 2 знаков; Text.numberFormat позволяет явно выбрать число знаков и разделители, что соответствует серверному форматированию, используемому в остальных payload'ах Bitrix24 REST.
  • addSpecification существует в основном для внутреннего использования. useFormatter() уже регистрирует каждую поддерживаемую страну при каждом вызове; сама IbanSpecification не экспортируется из @bitrix24/b24jssdk, поэтому расширение списка стран из кода приложения сегодня не является поддерживаемым публичным сценарием.