ngx-mask 20.0.3: автоматическая запятая в separator
Как настроить ngx-mask 20.0.3 для автоматической вставки десятичного разделителя (запятой) как в версии 7. Используйте mask="separator", [decimalMarker] и [thousandSeparator]. Примеры кода, отладка и альтернативы для ngx mask angular.
Как автоматически вставлять десятичный разделитель в ngx-mask 20.0.3?
Я использую ngx-mask 20.0.3 и столкнулся с проблемой с маской separator.2, которая работала иначе в версии 7.0.0.
В ngx-mask 7.0.0 я использовал этот код:
<input type="text" mask="separator.2" thousandSeparator="." decimalMarker="," prefix="" formnovalidate matInput formControlName="amount" required />
При вводе чисел, таких как 123, значение автоматически форматировалось как 1.23.
Однако в ngx-mask 20.0.3 запятая в качестве десятичного разделителя не вставляется автоматически. Я пробовал добавлять [leadZero]="true", но запятая все равно должна вводиться пользователем вручную.
Как настроить ngx-mask 20.0.3 для автоматической вставки запятой в качестве десятичного разделителя при вводе чисел пользователем, аналогично поведению в версии 7.0.0?
В консоли нет никаких ошибок, но значение 123 не форматируется как 1.23, что вызывает проблемы в моем приложении.
В ngx mask (ngx mask angular) 20.0.3 поведение маски с десятичными изменилось: вместо устаревшей separator.2 нужно использовать mask="separator" и передавать параметры как Angular inputs ([decimalMarker], [thousandSeparator]) — либо реализовать лёгкий форматтер, который вставляет запятую перед двумя последними цифрами. Ниже — конкретные варианты: быстрый HTML‑пример, рабочий компонент (reactive form), глобальная конфигурация и чеклист отладки.
Содержание
- Почему изменилась маска в ngx-mask?
- Быстрое решение: mask=“separator” (ngx mask angular)
- Пример кода: module + component + template
- Отладка: чеклист и типичные ошибки
- Альтернативы и патчи (leadZero, mask-паттерны, кастомный форматтер)
- Источники
- Заключение
Почему в ngx-mask изменилась маска separator? (ngx mask)
Коротко: поведение separator.2, которое автоматически «вставляло» разделитель перед двумя последними цифрами в старых версиях (v7 и т.д.), было переработано/убрано в более новых релизах. Разработчики унифицировали API: теперь используется mask="separator", а параметры вроде thousandSeparator, decimalMarker, prefix/suffix — вводятся как Inputs Angular (через квадратные скобки) и/или задаются глобально. Подробные обсуждения и баг‑репорты есть в репозитории проекта (пример запроса по поведению и желаемой автоматике — см. обсуждение на GitHub) и в связанных issue, где отмечают регрессии поведения между версиями: issue #733 и issue #1259. Документация старых версий (пример) показывает прежнее поведение, но в новых релизах синтаксис и семантика изменились — это причина, почему код из v7 не работает «из коробки» в 20.0.3.
Быстрое решение: настройка mask=“separator” (ngx mask angular)
Самый простой шаг — заменить mask="separator.2" на mask="separator" и передавать разделители как inputs:
<input
type="text"
mask="separator"
[thousandSeparator]="'.'"
[decimalMarker]="','"
[prefix]="''"
formnovalidate
matInput
formControlName="amount"
required
/>
Важно: использовать привязку через [] для thousandSeparator и decimalMarker (в новых версиях эти опции — inputs, а не простые атрибуты). Это описано в репозитории и README библиотеки — см. основной репозиторий: JsDaddy/ngx-mask и пример использования в README‑mirror unpkg README.
Но! это не всегда автоматически вставит запятую перед двумя последними цифрами при последовательном наборе “123” → “1,23”. Если поведение не сравнивается со старой v7, есть два надёжных варианта:
- Вариант A (быстрый): использовать небольшую обработку ввода, которая превращает строку цифр в формат с запятой перед двумя последними цифрами (см. пример ниже).
- Вариант B: попробовать альтернативную маску/шаблон (например,
mask="0*.00") — это обходной путь, который иногда даёт нужный результат (см. обсуждение на StackOverflow с примером0*.00) StackOverflow.
Пример кода: module + component + template
Ниже — рабочий пример для reactive form: показано, как склеить автоматическую вставку запятой (перед двумя последними цифрами) через небольшую функцию форматирования. Этот подход надёжен и не зависит от того, убрали ли separator.2 в API.
app.module.ts — глобальная конфигурация (варианты):
// Option A: старый стиль (forRoot)
import { NgModule } from '@angular/core';
import { NgxMaskModule } from 'ngx-mask';
@NgModule({
imports: [
NgxMaskModule.forRoot({
thousandSeparator: '.',
decimalMarker: ',',
dropSpecialCharacters: false // если хотите сохранять разделители в модели
})
]
})
export class AppModule {}
// Option B: новый стиль (provide)
import { NgModule } from '@angular/core';
import { provideNgxMask } from 'ngx-mask';
@NgModule({
providers: [
provideNgxMask({ thousandSeparator: '.', decimalMarker: ',', dropSpecialCharacters: false })
]
})
export class AppModule {}
component.ts — reactive form + форматтер:
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { debounceTime } from 'rxjs/operators';
@Component({
selector: 'app-amount',
templateUrl: './amount.component.html'
})
export class AmountComponent implements OnInit {
form = new FormGroup({
amount: new FormControl('')
});
ngOnInit() {
const ctrl = this.form.get('amount')!;
ctrl.valueChanges
.pipe(debounceTime(50))
.subscribe(val => {
// raw digits only
const digits = String(val || '').replace(/\D/g, '');
if (!digits) {
ctrl.setValue('', { emitEvent: false });
return;
}
// integer part is everything except last 2 digits
const intPart = digits.slice(0, -2) || '0';
const decPart = digits.slice(-2).padStart(2, '0');
// add thousand separators to integer part
const intWithSep = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
const formatted = `${intWithSep},${decPart}`;
if (formatted !== val) {
ctrl.setValue(formatted, { emitEvent: false });
}
});
}
}
component.html:
<input
type="text"
mask="separator"
[thousandSeparator]="'.'"
[decimalMarker]="','"
[prefix]="''"
formControlName="amount"
matInput
/>
Пояснение: логика берёт только цифры, формирует десятичную часть из двух последних цифр и обновляет контрол с уже отформатированной строкой. Это даёт ровно поведение старой separator.2 — ввод “123” превращается в “1,23”.
Отладка: чеклист и типичные ошибки
- Проверьте версию пакета:
npm ls ngx-maskилиpackage.json(страница пакета: npm ngx-mask). - Убедитесь, что вы используете
mask="separator", а неseparator.2(в v20separator.2может быть удалён/изменён). - Передавайте
thousandSeparatorиdecimalMarkerкак inputs:[thousandSeparator]="'.'"и[decimalMarker]="','"— не просто атрибуты. - Используйте
type="text", а неtype="number"— HTML number мешает форматированию. - Если хотите, чтобы в модели (FormControl.value) сохранялся форматированный текст с запятой/точками, поставьте
[dropSpecialCharacters]="false"или настройте глобально. - Проверяйте влияние Angular Material / сторонних директив (matInput) — иногда они взаимодействуют с событиями ввода.
- Если поведение кажется багом — посмотрите похожие issue/регрессии в репозитории: issue #733 и issue #1259.
Альтернативы и патчи (leadZero, mask-паттерны, кастомный форматтер)
- leadZero: опция
[leadZero]="true"помогает вводить значение, начинающееся с разделителя (например,.11→0,11), но не делает автоматическую вставку десятичного символа при наборе «123». - Альтернативная маска: некоторые решают задав
mask="0*.00"(пример решения — StackOverflow), это может автоматически показывать точку/запятую, но поведение отличается в разных версиях. - Кастомный форматтер (предложенный выше) — самый надёжный способ получить поведение из v7: вы полностью контролируете, как именно ввод превращается в формат с двумя десятичными знаками. Подход прост, транспарентен и легко тестируется.
Источники
- Currency mask without need to type decimal separator · Issue #733 · JsDaddy/ngx-mask · GitHub
- JsDaddy/ngx-mask — GitHub repository
- ngx-mask README (unpkg mirror)
- ngx-mask - Simple Decimal Mask Not working (StackOverflow)
- separator.2 not allowing decimals to be entered first (Issue #1259)
- ngx-mask — npm package page
Заключение
Если кратко: в ngx mask 20.0.3 замените separator.2 на mask="separator" и используйте [decimalMarker]="','" и [thousandSeparator]="'.'" как inputs; для поведения «вставлять запятую автоматически перед двумя последними цифрами» надёжно применять лёгкий форматтер на valueChanges (пример выше) или попробовать маску 0*.00. Этот подход восстанавливает поведение, похожее на ngx-mask v7, и решает проблему форматирования 123 → 1,23.