typescript - Angular 5 模板驅動的十進位輸入
我正在使用 Angular 5 的模板驅動表單,並且在表單中有幾個數字輸入欄位。
我的需求非常簡單,我感到驚訝的是我找不到解決方法
基本上,每個數字輸入應顯示為帶有千位分隔符和可配置小數位數的十進制,但在模型中應以數字(不帶逗號)形式存儲該值。
我已經看過一些管道,但它們不適用,因為它們僅用於顯示,無法與雙向綁定一起使用。我也四處搜尋了許多關於指令的範例,希望它能通過暴露控制項的 NgModel 並操作其數據來實現,但也沒有任何結果。
我看過在 TypeScript 中使用單向綁定加 setter,但那樣很醜而且不可重用
<input type="number" [NgModel]="somevalue | number : '2.2-6'" (ngModelChange)="somevalue = formatNumber($event)"
你能指引我正確的方向嗎?我認為指令是可行的方式,但我找不到清楚的範例說明如何將輸入綁定與顯示分開,更重要的是,如果模型中已有資料,要如何在載入時顯示正確的值
提前感謝你!
答案#1
Jeto 給了我 90% 的解決方案,經過幾個調整後,我成功得到了我想要的精確行為
我遵循了這篇文章,達到了一個狀態,字段顯示正常,但它總是顯示截斷的值。我真正想要的是一個純粹的“遮罩”,這樣用戶可以輸入超過兩位小數的數值,但為了清晰起見,只會看到兩位小數,並且當滑鼠移上去時可以顯示完整的數字。
然後我使用這篇文章在指令中暴露 NgModel,以便在聚焦時顯示 ngModel.viewmodel 的原始值,而不是被截斷的值
我的指令現在看起來是這樣(為了清楚起見去掉了管道符號。這是目前第一篇文章的剪切貼上)
import { Directive, Input, HostListener, ElementRef, OnInit } from "@angular/core";
import { NgModel } from "@angular/forms";
import { DecimalPipe } from "./decimal-pipe";
@Directive({
selector: "[decimalFormatter][ngModel]",
providers: [NgModel]
})
export class DecimalFormatterDirective implements OnInit {
private el: HTMLInputElement;
@Input('decimals') decimals: number;
constructor(
private elementRef: ElementRef,
private decimalPipe: DecimalPipe,
private ngModel: NgModel
) {
this.el = this.elementRef.nativeElement;
}
ngOnInit() {
if (this.decimals == null)
this.decimals = 2;
console.log(this.el);
console.log(this.ngModel);
this.el.value = this.decimalPipe.transform(this.el.value, this.decimals);
}
@HostListener("focus", ["$event.target.value"])
onFocus(value) {
console.log(this.el);
console.log(this.ngModel);
this.el.value = this.ngModel.viewModel; // opossite of transform
}
@HostListener("blur", ["$event.target.value"])
onBlur(value) {
console.log(this.el);
console.log(this.ngModel);
this.el.value = this.decimalPipe.transform(value, this.decimals);
}
}
編輯:小更新
我更改了它所調用的管道,從第一篇文章中的管道改為 Angular 實際使用的數字管道,所以它現在更像是一個包裝器,用於與雙向綁定一起使用的 Angular 管道。你也可以傳入 Angular 的數字格式化樣式,例如 2.2-6。
希望這能幫助將來遇到同樣問題的人!
指令:
import { Directive, Input, HostListener, ElementRef, OnInit } from "@angular/core";
import { NgModel } from "@angular/forms";
import { DecimalFormatPipe } from "./decimal-format-pipe";
@Directive({
selector: "[decimalFormatter][ngModel]",
providers: [NgModel]
})
export class DecimalFormatterDirective implements OnInit {
private el: HTMLInputElement;
@Input('decimals') decimals: string;
constructor(private elementRef: ElementRef,
private ngModel: NgModel,
private decimalFormatPipe: DecimalFormatPipe) {
this.el = this.elementRef.nativeElement;
}
ngOnInit() {
if (this.decimals == null)
this.decimals = "2.0-6";
console.log(this.el.value, this.decimals);
this.el.value = this.decimalFormatPipe.transform(this.el.value, this.decimals);
}
@HostListener("focus", ["$event.target.value"])
onFocus(value) {
console.log(this.el.value, this.decimals);
this.el.value = this.ngModel.viewModel; //Display the raw value on the model
}
@HostListener("blur", ["$event.target.value"])
onBlur(value) {
console.log(this.el.value, this.decimals);
this.el.value = this.decimalFormatPipe.transform(this.el.value, this.decimals);
}
}
管道包裝器
import { Pipe, PipeTransform, Inject, LOCALE_ID } from '@angular/core'
import { DecimalPipe } from '@angular/common';
@Pipe({ name: 'decimalFormatPipe' })
export class DecimalFormatPipe implements PipeTransform {
constructor(@Inject(LOCALE_ID) private locale: string) {}
transform(value: any, args: string) {
let pipe = new DecimalPipe(this.locale);
return pipe.transform(value, args);
}
}
以及在輸入上的使用
<input #myNumberInputCtrl="ngModel"
name="myNumberInput"
spellcheck="false"
placeholder="Enter a Number.."
[(ngModel)]="myNumberModel"
required
decimalFormatter
[decimals]="'0.0-6'"
/>
