AngularJS - 如何在我输入时在文本框上应用货币过滤器?

Posted

技术标签:

【中文标题】AngularJS - 如何在我输入时在文本框上应用货币过滤器?【英文标题】:AngularJS - How to apply currency filter on textbox as I type? 【发布时间】:2014-05-21 09:46:25 【问题描述】:

我的项目需要以货币格式显示金额字段。我可以实现这个onblur 事件,但是让我知道这是否可以使用过滤器或其他一些 AngularJS 技术来实现。

我有以下文本框:

<input type="text" class="form-control" id="MyAmount" name="MyAmount" ng-model="MyAmount" />

我想将此文本框中的值转换为货币格式。因此,如果我输入 200,000,那么在我输入时或在输入时它应该是 $200,000.00。

我使用了以下技术并应用了过滤器,

<input type="text" class="form-control" id="MyAmount" name="MyAmount" ng-model="MyAmount"
                            value="MyAmount | currency" />

但它只转换我输入的第一个键,就像它将 2 转换为 $2.00 然后它清除值(因为我猜它发现这个更新的值不是数字?)

更新:我可以使用自定义过滤器对其进行实时格式化,但该过滤器在所有情况下都无法正常工作,当我保存该值时,我得到的值中包含 $ 和逗号,而不仅仅是数值。我会尝试更多。

【问题讨论】:

【参考方案1】:

这是一个相当重要的问题。 对于功能的主要部分,您需要使用ngModelController$formatters$parsers属性来注册监听器以分别处理$modelValue$viewValue的变化。

    $modelValue 发生变化时,您需要先使用currency 过滤器对其进行过滤,然后再将其显示到视图中。

    $viewValue 发生变化时,您需要将其转换为数字(我认为将模型值存储为数字而不是格式化字符串更有意义),通过@987654332 过滤该数字@过滤并更新$viewValue(如有必要)。

这并不是特别困难。棘手的部分是更新元素的值,将光标移动到末尾,因此您需要手动重新定位插入符号。

我的尝试导致了以下指令定义对象


  restrict: 'A',
  require: 'ngModel',
  link: function postLink(scope, elem, attrs, modelCtrl)     
    modelCtrl.$formatters.push(filterFunc);
    modelCtrl.$parsers.push(function (newViewValue) 
      var newModelValue = toNumber(newViewValue);
      modelCtrl.$viewValue = filterFunc(newModelValue);
      var pos = getCaretPosition(elem[0]);
      elem.val(modelCtrl.$viewValue);
      var newPos = pos + modelCtrl.$viewValue.length -
                         newViewValue.length;
      setCaretPosition(elem[0], newPos);
      return newModelValue;
    );
  
;

另请参阅此short demo。它并不完美,但它是一个好的开始。 顺便说一句,我从 AngularUI 的 uiMask 指令中“借用”了get/setCaretPosition() 函数。

【讨论】:

谢谢,现在我对我应该做什么有了更好的理解。我会尝试你的解决方案。但是该演示仅采用单个数字值,例如 $2.00 等。我必须手动将光标移动到小数点之前,然后再次键入以输入更多数字。请看一看。我正在使用最新版本的 Chrome。 我不明白你的意思。我可以输入任何数字(例如:对于$2,123.00,我将光标放在小数点分隔符之前并输入2123)。你到底什么意思 ? (我也在 Windows 上使用最新版本的 Chrome。) 是的,如果我将光标放在小数点分隔符之前,它可以完美运行。但我的文本框最初是空白的,我将从空白开始输入。在您的演示中,我可以从空白值开始吗?谢谢。 一切皆有可能。你只需要实现它:) 查看我更新的小提琴。就像我说的,这不是最终的解决方案,但它是一个很好的陈述点。但是您必须根据您的具体要求对其进行修改。 (如果它帮助您解决了问题,请不要忘记访问答案。) @RafaelMerlin:事情就是这样工作的:) 为$viewValue 分配新值不会自动设置元素的值。通常,你会调用$render(),但这是一种特殊情况,因为我们要捕获并重置插入符号的位置,所以我们必须手动进行(或覆盖控制器的$render() 方法)。【参考方案2】:

您还可以使用自动为您提供此功能的fcsa-number 指令。就像将fcsa-number 属性添加到输入元素一样简单。

<input type="text" fcsa-number />

还有here is a demo

源代码和文档在 GitHub 上可用:https://github.com/FCSAmericaDev/angular-fcsa-number

【讨论】:

【参考方案3】:

我在尝试构建自定义货币指令时遇到了同样的问题。因此,在检查了许多解决方法后,我找到了angular-input-masks 指令。

支持 bower 快速安装和使用只需在输入文本元素上添加 ui-money-mask 属性:

<input type="text" ng-model="money" ui-money-mask>

还支持最小值和最大值验证。

【讨论】:

angular-input-masks 唯一的问题是它不自动调整光标,也不支持设置动态 $locale。 有问题的解决方案。

以上是关于AngularJS - 如何在我输入时在文本框上应用货币过滤器?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jQuery 在页面加载时关注表单输入文本字段?

如何在输入文本时在文本输入字段中应用自定义字体?

成功完成初始自动完成后,如何在 WinForm 文本框上重新启动自动完成?

如何将焦点设置在文本框或密码框上

AngularJS - 使用 angularjs 拖放列表库时在 html 页面中没有得到任何东西

按下 Enter 按钮后将光标保持在文本框上