Angular iMask插件unmask设为'typed'时触发空值读取错误求助
Angular 16 + iMask: 解决
unmask='typed'的空值错误并实现数字类型绑定 问题重现
在Angular 16中用iMask做价格输入格式化时,设置[unmask]="'typed'"期望把book.price存为数字类型,却触发了空值读取错误:
ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of null (reading 'toLocaleString') TypeError: Cannot read properties of null (reading 'toLocaleString') at MaskedNumber.format (number.js:301:18) at MaskedNumber.typedValueEquals (base.js:377:127) at MaskedNumber.typedValueEquals (number.js:285:19) ...
改用[unmask]="true"不会报错,但price会被存为带千分位的字符串,不符合数字类型的存储需求。
错误原因
从报错栈能看出,问题出在iMask初始化阶段:当设置unmask='typed'时,Angular表单控件初始化过程中,iMask尝试对book.price的初始值(默认0)执行类型校验和格式化,但此时mask实例的内部属性尚未完全就绪,导致读取null值的toLocaleString方法,触发报错。
解决方案
方案1:手动处理值转换(推荐)
放弃unmask='typed',改用unmask=true配合ngModelChange手动将格式化后的字符串转为数字,既避免初始化错误,又保证price为数字类型:
- 修改模板,将双向绑定改为单向绑定+事件监听:
<input type="text" class="form-control" placeholder="Price" [ngModel]="book.price" id="book" name="book" #bookInput="ngModel" [imask]="currencyMask" [unmask]="true" (ngModelChange)="onChange($event)" />
- 在组件中实现转换逻辑:
onChange(formattedValue: string) { // 移除千分位逗号,转换为数字,空值时设为0 this.book.price = formattedValue ? Number(formattedValue.replace(/,/g, '')) : 0; }
方案2:调整mask配置添加默认值
在currencyMask中添加defaultValue: 0,确保iMask初始化时能正确识别初始值,之后可保留[unmask]="'typed'":
currencyMask={ mask: Number, scale: 2, thousandsSeparator: ',', padFractionalZeros: true, normalizeZeros: true, radix: '.', mapToRadix: ['.'], min:0, defaultValue: 0 // 添加默认值配置 };
验证效果
两种方案都能实现:
- 前端输入框显示带千分位、保留两位小数的格式化价格
book.price始终以数字类型存储,满足业务需求
内容的提问来源于stack exchange,提问作者Adora González
相关产品推荐
相关产品推荐

