Angular 4两位小数数字输入指令问题及修复咨询
修复方案:允许先输入小数点并在前方输入数字
我看了你的OnlyNumber指令,问题出在当输入框值为.时,parseFloat(e.target.value)得到NaN,加上原有的minValue判断逻辑可能错误阻止了数字输入,同时光标位置的处理也没考虑到在小数点前输入的场景。下面是修复后的完整代码,以及关键修改点说明:
import { Directive, ElementRef, HostListener, Input } from '@angular/core'; @Directive({ selector: '[OnlyNumber]' }) export class OnlyNumber { elemRef: ElementRef; constructor(private el: ElementRef) { this.elemRef = el; } @Input() OnlyNumber: boolean; @Input() DecimalPlaces: string; @Input() minValue: string; @Input() maxValue: string; @HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent) { if (!this.OnlyNumber) return; // 允许控制键和导航键 const allowedKeys = [46, 8, 9, 27, 13, 110, 190]; if (allowedKeys.includes(event.keyCode) || // Ctrl+A/C/X 快捷键 (event.keyCode === 65 && event.ctrlKey) || (event.keyCode === 67 && event.ctrlKey) || (event.keyCode === 88 && event.ctrlKey) || // 方向键、home/end (event.keyCode >= 35 && event.keyCode <= 39)) { return; } // 阻止非数字键(数字小键盘除外) if ((event.shiftKey || (event.keyCode < 48 || event.keyCode > 57)) && (event.keyCode < 96 || event.keyCode > 105)) { event.preventDefault(); } } @HostListener('keypress', ['$event']) onKeyPress(event: any) { if (!this.OnlyNumber) return; const inputValue = this.elemRef.nativeElement.value; const currentCursorPos = this.elemRef.nativeElement.selectionStart; const isCursorBeforeDot = inputValue.includes('.') && currentCursorPos <= inputValue.indexOf('.'); const newChar = event.key; // 处理minValue判断:兼容空输入或仅小数点的场景 if (this.minValue) { const min = parseFloat(this.minValue); let tempValue: number; if (inputValue === '' || inputValue === '.') { tempValue = parseFloat(newChar + inputValue); } else { tempValue = parseFloat(inputValue); } if (!isNaN(tempValue) && tempValue < min) { event.preventDefault(); } } // 处理maxValue判断:根据光标位置计算输入后的临时值 if (this.maxValue) { const max = parseFloat(this.maxValue); let tempValue: number; if (inputValue === '.' || inputValue === '') { tempValue = parseFloat(newChar + inputValue); } else if (isCursorBeforeDot) { tempValue = parseFloat(inputValue.slice(0, currentCursorPos) + newChar + inputValue.slice(currentCursorPos)); } else { tempValue = parseFloat(inputValue + newChar); } if (!isNaN(tempValue) && tempValue > max) { event.preventDefault(); } } // 处理小数位数限制:仅光标在小数点后时生效 if (this.DecimalPlaces) { const decimalPlaces = parseInt(this.DecimalPlaces); const dotCount = (inputValue.match(/\./g) || []).length; const decimalPartLength = inputValue.split('.')[1]?.length || 0; // 阻止输入多个小数点 if (dotCount >= 1 && newChar === '.') { event.preventDefault(); return; } // 只有光标在小数点后时,才限制小数位数 if (!isCursorBeforeDot && dotCount === 1) { const newDecimalLength = decimalPartLength + (/\d/.test(newChar) ? 1 : 0); if (newDecimalLength > decimalPlaces) { event.preventDefault(); } } } } // 可选优化:失去焦点时自动补全小数点前的0(比如`.`变成`0.`) @HostListener('blur') onBlur() { const inputValue = this.elemRef.nativeElement.value; if (inputValue === '.') { this.elemRef.nativeElement.value = '0.'; } } }
关键修改说明:
- 光标位置精准判断:新增
isCursorBeforeDot变量,明确区分光标在小数点前后的场景,确保在小数点前输入数字不受小数位数限制。 - minValue逻辑修复:专门处理输入框为空或仅含小数点的情况,通过计算临时值(输入数字+当前值)判断是否符合最小值要求,避免
NaN导致的错误阻止。 - maxValue逻辑完善:根据光标位置动态计算输入后的临时值,不管光标在小数点前还是后,都能准确校验是否超过最大值。
- 小数位数限制优化:仅当光标在小数点后方时,才触发小数位数限制,彻底解决了无法在小数点前输入数字的问题。
- 可选体验优化:新增
blur事件处理,当输入框只剩小数点时,自动补全为0.,避免用户输入不合法的格式。
使用注意:
- 若设置
minValue="0",允许输入0.xx格式;若设置minValue="1",则会阻止0.xx这类小于1的输入。 - 保留了原有的快捷键支持(Ctrl+A/C/X、删除键、方向键等),不影响用户常规操作习惯。
内容的提问来源于stack exchange,提问作者Hacker
相关产品推荐
相关产品推荐

