You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

处理本地小数分隔符的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绑定的值自动转换为标准点分隔符,方便后续业务计算。
  • 粘贴处理:过滤粘贴内容中的非法字符,确保粘贴后内容符合规则。

使用方法

  1. 在Angular模块中声明该指令:
import { NgModule } from '@angular/core';
import { DecimalNumbersOnlyDirective } from './decimal-numbers-only.directive';

@NgModule({
  declarations: [DecimalNumbersOnlyDirective]
})
export class YourModule { }
  1. 在输入框中使用:
<input type="text" decimalNumbersOnly [(ngModel)]="decimalValue">

内容的提问来源于stack exchange,提问作者Jakob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:35:24