Angular 2实现ng-model输入值货币格式化且保持模型数值型
Angular 2+ 货币格式化输入指令(保持模型数值类型)
我来帮你实现完全符合需求的指令——输入框显示带货币符号的格式化字符串,但绑定的模型值始终保持数值类型,完美解决你之前遇到的服务器加载值后模型变字符串的问题。
指令实现代码
这个指令基于ControlValueAccessor实现,它是Angular表单控件和模型之间的桥梁,能精准控制视图与模型的双向转换:
import { Directive, ElementRef, HostListener, forwardRef } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; @Directive({ selector: '[appCurrencyInput]', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CurrencyInputDirective), multi: true } ] }) export class CurrencyInputDirective implements ControlValueAccessor { private onChange: (value: number) => void; private onTouched: () => void; private element: HTMLInputElement; constructor(private el: ElementRef) { this.element = el.nativeElement; } // 模型 → 视图:把数值格式化为带货币符号的两位小数字符串 writeValue(value: number): void { if (value !== null && value !== undefined && !isNaN(value)) { this.element.value = `$ ${value.toFixed(2)}`; } else { this.element.value = ''; } } registerOnChange(fn: (value: number) => void): void { this.onChange = fn; } registerOnTouched(fn: () => void): void { this.onTouched = fn; } setDisabledState(isDisabled: boolean): void { this.element.disabled = isDisabled; } // 视图 → 模型:处理用户输入,提取纯数字并转为数值类型 @HostListener('input', ['$event.target.value']) onInput(value: string): void { // 过滤掉所有非数字、非小数点的字符 const numericValue = value.replace(/[^0-9.]/g, ''); // 处理多个小数点的情况,只保留第一个且最多两位小数 const parts = numericValue.split('.'); let cleanValue = parts[0]; if (parts.length > 1) { cleanValue += `.${parts[1].slice(0, 2)}`; } // 转换为数值(空值则设为null) const modelValue = cleanValue ? parseFloat(cleanValue) : null; // 更新模型值 this.onChange(modelValue); // 重新格式化输入框显示 this.writeValue(modelValue); } // 失去焦点时确保格式规范(比如输入整数自动补两位小数) @HostListener('blur') onBlur(): void { this.onTouched(); const currentRawValue = this.element.value.replace(/[^0-9.]/g, ''); if (currentRawValue && !isNaN(parseFloat(currentRawValue))) { this.writeValue(parseFloat(currentRawValue)); } } }
使用步骤
在模块中声明指令
把指令添加到你的Angular模块的declarations数组中:import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { CurrencyInputDirective } from './currency-input.directive'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent, CurrencyInputDirective], imports: [BrowserModule, FormsModule, ReactiveFormsModule], bootstrap: [AppComponent] }) export class AppModule { }在模板中使用
不管是模板驱动表单还是响应式表单,直接给输入框添加指令即可:<!-- 模板驱动表单 --> <input type="text" appCurrencyInput [(ngModel)]="productPrice" placeholder="Enter price"> <!-- 响应式表单 --> <input type="text" appCurrencyInput formControlName="productPrice" placeholder="Enter price">
关键特性说明
- 模型始终为数值类型:不管是初始赋值(比如从服务器加载的数值)还是用户输入,绑定的模型值都是
number类型,不会变成字符串。 - 自动格式化显示:模型值为
2时,输入框显示$ 2.00;用户输入123,失去焦点后自动转为$ 123.00。 - 输入过滤:自动过滤非数字字符(除了小数点),用户输入
$ abc123.456会被处理为$ 123.45,模型值为123.45。 - 兼容服务器加载场景:当从服务器获取数值赋值给模型时,指令会自动格式化显示,同时保持模型的数值类型。
内容的提问来源于stack exchange,提问作者Saima Gul
相关产品推荐
相关产品推荐

