我正在尝试找到一种方法,在初始页面加载(通过角度服务将数据获取到后端,即可观察/订阅)时以百分比(例如 97,52%)显示 html 输入字段,但也有此输入当我编辑它时(即引发 DOM(焦点)事件时),字段会丢失它的百分比格式。
格式的数据绑定到模型。我们将模型字段称为 myModel.percentNumber,其中 percentNumber=1 表示“100 %”(0.69 表示“69 %”或再次为 100 表示“10 000 %”)
因此,当我单击指示“97,52 %”的字段时,我希望它变为“97.52”,但模型中的数据绑定值应该是 0.9752,因为这是我需要存储的。
该字段应该使用 ngModel 绑定。
注意:这应该适用于国际化,所以我不能使用基于删除空格、替换“。”的“脏”解决方案。by ',' ...在这里你可以看到我举了一个例子,其中格式化的百分比值应该有一个逗号作为小数分隔符和一个空格作为千位分隔符,但这取决于用户的本地化。
到目前为止,我已经尝试了一些东西,但没有一个能解决所有问题。
1)以2路绑定为起点,即
<input [(ngmodel)]="myModel.percentNumber | percent:'1.2-2'">
...但它确实会导致管道出现问题:
未捕获的错误:模板解析错误:
2)从我想要的2路绑定短语法到长语法,即
<input [ngmodel]="myModel.percentNumber | percent:'1.2-2'" (ngModelChange)="myModel.percentNumber = $event">
这允许在初始加载时以百分比形式具有正确的格式(在来自后端的响应中,如果 myModel.percentNumber=0.9752 它正确显示为 '97,52 %'),但是,当您单击输入进行编辑时它,当我希望它显示“97.52”时,格式会保持不变(),例如 PercentPipe.parse() 之类的东西(不存在)。这将需要为您应该具有此行为的每个字段添加(焦点)事件处理程序。可重用性会很低。我相信角度指令方法应该是可取的。
3) 使用角度指令:我创建了一个PercentFormatterDirective
带有选择器的指令percentFormatter
和一个字符串类型的输入percentDigits
,该输入将接受与 PercentPipe 相同的格式(即 digitInfo)。一个使用示例是:
<input percentFormatter percentDigits="1.2-2" [ngModel]="myModel.percentNumber" (ngModelChange)="myModel.percentNumber = $event">
我宁愿不必在 [ngModel] 中仍然使用“正常” PercentPipe,因为它需要编写 digitInfo1.2-2
两次(即我不想写 <input percentFormatter percentDigits="1.2-2" [ngModel]="myModel.percentNumber | percent:'1.2-2'" (ngModelChange)="myModel.percentNumber = $event">
我可以在单击输入(焦点)时格式化值,正如我在 PercentFormatterDirective 中作为(焦点)事件的侦听器实现的那样:
@HostListener("focus", ["$event.target.value"])
onfocus(value) {
if (value) {
// we have to do the oposite than the transform (e.g. we want to go from % to number)
this.htmlInputElement.value = this.parse(value);
}
}
因此,当我在该字段中单击时,这会从 '97,52 %' 到 '97.52' 得到满足。在这里,我不会详细介绍我创建的 parse() 方法(您只需要知道它是有效的,并且基于我用来获取用户本地化的 PercentPipe 和此查找是小数分隔符和千位分隔符)。
我还可以在离开输入字段时将值格式化为百分比格式,正如我在 PercentFormatterDirective 中作为 (blur) 事件的侦听器所实现的那样:
@HostListener("blur", ["$event.target.value"])
onblur(value) {
if ((value as string).indexOf('%') === -1) {
this.formatNumberInPercent('100for100percent');
}
}
所以当我离开现场时,这会从 '97.52' 到 '97,52 %' 得到满足。在这里,我不会详细介绍 formatNumberInPercent() 方法(您只需要知道它有效并且基于 PercentPipe.transform() 方法,但是在 PercentPipe.transform() 之前将值除以 100 会得到你从 '0.9752' 到 '97,52 %' 但在我的输入中我有 '97.52' 这显然是用户要输入的)
这个问题是在初始加载时(更确切地说,当通过 observable/subscribe 从后端返回时,当 myModel.percentNumber 设置时),来自 PercentFormatterDirective 的(焦点)或(模糊)@HostListener 都不会被称为没有与 DOM 的用户交互。如果我在 PercentFormatterDirective 中添加一个 ngOnInit(),那么是的,我可以格式化绑定值(即使用我创建的自定义方法将“0.9752”转换为“97,52 %”,该方法formatNumberInPercent('100for100percent')
再次使用 PercentPipe.transform() 方法,但是不将值除以 100)...但是,如果我直接在组件中绑定数据,则此方法有效,ei 不使用可观察/订阅。当使用 observable/subscribe(我必须使用)从后端获取答案时,ngOnInit()
PercentFormatterDirective 的已执行。
当获得响应(来自可观察/订阅)时,我需要能够执行格式化。我尝试添加ngOnChanges(changes: SimpleChanges)
PercentFormatterDirective(然后用 读取 SimpleChange 的 de 数组for (let propName in changes)
),但是我没有看到来自 myModel.percentNumber 的新绑定值。似乎ngOnChanges(changes: SimpleChanges)
只提供了一个 SimpleChange 数组,其属性对应于我的指令输入(即 percentDigits)。
我已经private elementRef: ElementRef
注入了指令的构造函数,但正如我所说的,ngOnChanges()
我无法获得 myModel.percentNumber 的值(this.elementRef.nativeElement.value
给我“”,从来没有任何值)。
也许我在生命周期中还为时过早?
或者也许应该采取另一种方法?
如果您有任何建议,我会很高兴听到它提出来!:)