Angular使用正则exec验证器限制MatInput输入并保持可编辑的实现方法
结论
不可以直接将该验证器作为动态maxlength属性实现需求,原因是maxlength仅限制输入的总字符数,无法适配「小数点前最多6位、小数点后最多2位」的分段校验规则,举个反例:如果把总长度设为8(6位整数+小数点+2位小数的最大长度),用户输入纯整数1234567时,总长度仅7位未触发maxlength限制,但已经违反了整数位最多6位的规则。
前置修正:你的验证器逻辑写反了
Angular 自定义验证器的规则是:校验通过返回null,校验不通过返回错误对象,你当前的代码刚好写反了,会导致符合规则的内容被判定为校验失败,先修正:
public static floatingAmount(c: FormControl) { const reg = /^[0-9]{1,6}([,.][0-9]{1,2})?$/; const isValid = reg.test(c.value); return isValid ? null : { floatingAmount: true }; }
正确实现方案
要实现「不符合规则的内容禁止输入」的效果,推荐监听输入框的input事件做实时内容过滤,配合验证器做兜底校验即可:
模板代码
<mat-form-field> <input matInput [formControl]="amountControl" (input)="handleAmountInput($event)" placeholder="输入金额"> <!-- 校验错误提示 --> <mat-error *ngIf="amountControl.hasError('floatingAmount')"> 最多支持6位整数、2位小数 </mat-error> </mat-form-field>
组件逻辑代码
// 输入事件处理,实时过滤非法内容 handleAmountInput(event: Event): void { const inputEl = event.target as HTMLInputElement; let inputVal = inputEl.value; // 第一步:过滤掉所有非数字、小数点、逗号的字符 inputVal = inputVal.replace(/[^0-9,.]/g, ''); const separatorIndex = Math.max(inputVal.indexOf('.'), inputVal.indexOf(',')); if (separatorIndex > -1) { // 存在小数点/逗号:限制整数位最多6位,小数位最多2位 const intPart = inputVal.slice(0, separatorIndex).slice(0, 6); const decimalPart = inputVal.slice(separatorIndex + 1).slice(0, 2); inputVal = `${intPart}.${decimalPart}`; } else { // 无小数点:最多6位整数 inputVal = inputVal.slice(0, 6); } // 把处理后的值回写到输入框和表单控件 inputEl.value = inputVal; this.amountControl.setValue(inputVal, { emitEvent: false }); }
这个方案可以完全符合你的需求,输入过程中就会自动拦截不符合规则的内容,不会允许用户输入超出限制的数字。
内容的提问来源于stack exchange,提问作者Jonny
相关产品推荐
相关产品推荐

