处理本地小数分隔符的Angular十进制数字输入指令开发需求
Angular 十进制数字输入自定义指令(兼容本地分隔符)
直接上满足需求的实现代码,指令会自动适配用户系统的小数分隔符,同时严格限制输入规则:
import { Directive, ElementRef, HostListener, OnInit } from '@angular/core'; import { NgControl } from '@angular/forms'; @Directive({ selector: '[decimalNumbersOnly]' }) export class DecimalNumbersOnlyDirective implements OnInit { private decimalSeparator: string; private regexPattern: RegExp; constructor( private el: ElementRef, private control: NgControl ) {} ngOnInit(): void { // 获取当前环境的小数分隔符(逗号或点) this.decimalSeparator = new Intl.NumberFormat().formatToParts(0.1)[1].value; // 构建正则:允许数字、单个小数分隔符,支持开头是分隔符(如.456)或前导零(如0.123) this.regexPattern = new RegExp(`^\\d*\\${this.decimalSeparator}?\\d*$`); } @HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent): void { // 允许控制键:退格、删除、箭头、制表符等 const allowedKeys = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab']; if (allowedKeys.includes(event.key)) { return; } // 禁止负号输入 if (event.key === '-') { event.preventDefault(); return; } // 提前验证输入后的内容是否合法 const currentValue = this.el.nativeElement.value; const newValue = currentValue + event.key; if (!this.regexPattern.test(newValue)) { event.preventDefault(); } } @HostListener('input', ['$event']) onInput(event: InputEvent): void { let value = this.el.nativeElement.value; // 移除所有非法字符(只保留数字和小数分隔符) const cleanedValue = value.replace(new RegExp(`[^\\d${this.decimalSeparator}]`, 'g'), ''); // 确保只有一个小数分隔符 const parts = cleanedValue.split(this.decimalSeparator); if (parts.length > 2) { value = parts[0] + this.decimalSeparator + parts.slice(1).join(''); } else { value = cleanedValue; } // 更新输入框显示值 this.el.nativeElement.value = value; // 同步到ngModel,转换为标准点分隔符方便后续业务处理 if (this.control && this.control.control) { const modelValue = value.replace(this.decimalSeparator, '.'); this.control.control.setValue(modelValue, { emitEvent: false }); } } @HostListener('paste', ['$event']) onPaste(event: ClipboardEvent): void { event.preventDefault(); const clipboardData = event.clipboardData?.getData('text') || ''; // 过滤粘贴内容中的非法字符 const cleanedText = clipboardData.replace(new RegExp(`[^\\d${this.decimalSeparator}]`, 'g'), ''); // 合并到当前值并处理 const currentValue = this.el.nativeElement.value; const newValue = currentValue + cleanedText; const parts = newValue.split(this.decimalSeparator); let finalValue = parts.length > 2 ? parts[0] + this.decimalSeparator + parts.slice(1).join('') : newValue; // 更新输入框和ngModel this.el.nativeElement.value = finalValue; if (this.control && this.control.control) { const modelValue = finalValue.replace(this.decimalSeparator, '.'); this.control.control.setValue(modelValue, { emitEvent: false }); } } }
关键逻辑说明
- 本地分隔符适配:通过
Intl.NumberFormat自动获取当前用户系统的小数分隔符,无需手动配置。 - 输入限制:
- 直接拦截负号输入,禁止负数。
- 只允许数字和单个小数分隔符,支持
.456或0.123这类格式。
- 输入与模型同步:输入框显示本地分隔符格式,但ngModel绑定的值自动转换为标准点分隔符,方便后续业务计算。
- 粘贴处理:过滤粘贴内容中的非法字符,确保粘贴后内容符合规则。
使用方法
- 在Angular模块中声明该指令:
import { NgModule } from '@angular/core'; import { DecimalNumbersOnlyDirective } from './decimal-numbers-only.directive'; @NgModule({ declarations: [DecimalNumbersOnlyDirective] }) export class YourModule { }
- 在输入框中使用:
<input type="text" decimalNumbersOnly [(ngModel)]="decimalValue">
内容的提问来源于stack exchange,提问作者Jakob
相关产品推荐
相关产品推荐

