【发布时间】:2018-04-21 12:26:34
【问题描述】:
我正在尝试找到一种方法,在初始页面加载(通过角度服务获取到后端的数据,即可观察/订阅)时以百分比(例如 97,52 %)显示 html 输入字段,但也当我编辑它时(即引发 DOM(焦点)事件时),让这个输入字段松散它的百分比格式。
格式的数据绑定到模型。我们将模型字段称为 myModel.percentNumber,其中 percentNumber=1 表示“100 %”(0.69 表示“69 %”或再次为 100 表示“10 000 %”)
因此,当我单击指示“97,52 %”的字段时,我希望它变为“97.52”,但模型中的数据绑定值应为 0.9752,因为这是我需要存储的值。
该字段应该使用 ngModel 绑定。
注意:这应该适用于国际化,所以我不能使用基于删除空格、替换“。”的“脏”解决方案。经过 ',' ... 在这里你可以看到我举了一个例子,其中格式化的百分比值应该有一个逗号作为小数分隔符和一个空格作为千位分隔符,但这取决于用户的本地化。
到目前为止,我已经尝试了一些方法,但都没有解决所有问题。
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.transform() 相反的操作,例如类似 PercentPipe.parse() 的东西(不存在)。这将需要为您应该具有此行为的每个字段添加(焦点)事件处理程序。可重用性会很低。我相信角度指令方法应该是可取的。
3) 带有角度指令:我创建了一个指令PercentFormatterDirective,带有一个选择器percentFormatter 和一个字符串类型的输入percentDigits,它可以接受与PercentPipe 相同的格式(即digitInfo )。一个使用示例是:
<input percentFormatter percentDigits="1.2-2" [ngModel]="myModel.percentNumber" (ngModelChange)="myModel.percentNumber = $event">
我宁愿不必在 [ngModel] 中仍然使用“正常” PercentPipe,因为它需要编写 digitInfo 1.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' 这显然是用户要输入的)
这个问题是在初始加载时(更确切地说,当设置了 myModel.percentNumber 从后端返回时,通过 observable/subscribe 时), (focus) 或 ( blur) PercentFormatterDirective 中的 @HostListener 被调用,因为没有用户与 DOM 交互。
如果我在 PercentFormatterDirective 中添加一个 ngOnInit(),那么是的,我可以格式化绑定值(即使用我创建的名为 formatNumberInPercent('100for100percent') 的自定义方法将“0.9752”转换为“97,52 %”,该方法再次使用 PercentPipe.transform( ) 方法,但没有将值除以 100)...但是,如果我直接在组件中绑定数据,则此方法有效,ei不使用可观察/订阅。
当使用 observable/subscribe(我必须使用)从后端获取答案时,PercentFormatterDirective 的ngOnInit() 已经被执行。
当获得响应(来自可观察/订阅)时,我需要能够执行格式化。我尝试在 PercentFormatterDirective 中添加 ngOnChanges(changes: SimpleChanges)(然后使用 for (let propName in changes) 读取 SimpleChange 的 de 数组),但是我没有看到来自 myModel.percentNumber 的新绑定值。似乎ngOnChanges(changes: SimpleChanges) 只提供了一个 SimpleChange 数组,其属性对应于我的指令输入(即 percentDigits)。
我在指令的构造函数中注入了private elementRef: ElementRef,但正如我在ngOnChanges() 中所说的,我无法获得 myModel.percentNumber 的值(this.elementRef.nativeElement.value 给了我“”,但从来没有任何值)。
也许我的生命周期还为时过早?
或者应该采取其他方法?
如果您有任何建议,我会很高兴听到您提出来! :)
【问题讨论】:
-
问题解决了吗?
标签: angular data-binding pipe directive ngmodel