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

如何修复Angular 8指令正则表达式以支持负小数?

问题分析与解决方案

你的问题出在实时输入的中间状态校验上:在线测试正则时你输入的是完整的负小数(比如-12.34),但指令是在每一次按键时校验输入后的即时值——当你第一次输入负号-时,next的值是"-",而你修改后的正则/^-?[0-9]\d*(\.\d+)?$/g并不匹配这个单独的负号,所以被event.preventDefault()阻止了输入。

另外,原指令是限制最多两位小数的,你的新正则没有保留这个限制,同时全局标志g在这里也不需要,会干扰匹配逻辑。

修改后的完整指令代码

import {Directive, ElementRef, HostListener} from '@angular/core';

@Directive({
    selector: '[signedNumeric]'
})

export class SignedNumericDirective {
    // 允许三种状态:空、单独负号、正负两位小数
    private regex = {               
        decimal: new RegExp(/^$|^-$|^-?\d+(?:\.\d{0,2})?$/)
    };                           
    private specialKeys = {       
        decimal: [ 'Backspace', 'Delete', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ]
    };

    constructor(private el: ElementRef) {
    }

    @HostListener('keydown', [ '$event' ])
    onKeyDown(event: KeyboardEvent) {
        // 特殊按键直接放行
        if (this.specialKeys['decimal'].indexOf(event.key) !== -1) {
            return;
        }

        const current: string = this.el.nativeElement.value;
        // 已有负号时,禁止再次输入负号
        if (current.includes('-') && event.key === '-') {
            event.preventDefault();
            return;
        }

        const next: string = current.concat(event.key);
        // 校验输入后的值是否合法
        if (next && !next.match(this.regex['decimal'])) {
            event.preventDefault();
        }
    }
}

关键修改点说明

  1. 正则表达式调整:

    • ^$:允许输入框为空
    • ^-$:允许单独输入负号(作为输入负小数的中间状态)
    • ^-?\d+(?:\.\d{0,2})?$:允许正负整数、最多两位小数的正负小数,保留原指令的小数位数限制
  2. 增加负号重复输入拦截:

    • 判断当前输入框已有负号时,阻止再次输入负号,避免出现--123这类非法值
  3. 移除全局标志g:

    • 单值匹配不需要全局标志,g会导致match方法返回数组而非布尔值(在某些场景下会干扰校验逻辑)

测试验证

现在可以正常输入以下内容:

  • 负号开头的小数:-12.34、-0.5、-100
  • 正小数:34.45、0.7、1200
  • 输入过程中的中间状态:先输-,再输数字,再输小数点和小数位

同时会拦截以下非法输入:

  • 多个负号:--12
  • 超过两位小数:-12.345
  • 非数字/负号/小数点的字符:abc、-12a

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:35:26