Обзор
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, поэтому расширение списка стран из кода приложения сегодня не является поддерживаемым публичным сценарием.