【问题标题】:NgModelOptions + Currency Filter = Field not displaying modelNgModelOptions + 货币过滤器 = 字段不显示模型
【发布时间】:2015-10-24 09:00:25
【问题描述】:

我有几个表单字段需要以美元 ($n.nn) 显示,并且已成功使用自定义货币指令。但是我添加了 NgModelOptions 来控制去抖动:

{ updateOn: '默认模糊', debounce: { 'default':100, 'blur': 0 } }"

这可以正常工作,除非字段更新然后快速退出,在这种情况下会显示先前的值。输入然后离开该字段将导致显示正确的值。

关于如何将指令或货币过滤器与 NgModelOptions 组合以便显示的值反映退出时的模型值的任何想法?

这是当前指令:

.directive('ngCurrency', function ($filter, $locale) {
      return {
        require: 'ngModel',
        scope: {
          min: '=min',
          max: '=max',
          ngRequired: '=ngRequired'
        },
        link: function (scope, element, attrs, ngModel) {

          function decimalRex(dChar) {
            return RegExp("\\d|\\" + dChar, 'g');
          }

          function clearRex(dChar) {
            return RegExp("((\\" + dChar + ")|([0-9]{1,}\\" + dChar + "?))&?[0-9]{0,2}", 'g');
          }

          function decimalSepRex(dChar) {
            return RegExp("\\" + dChar, "g");
          }

          function clearValue(value) {
            value = String(value);
            var dSeparator = $locale.NUMBER_FORMATS.DECIMAL_SEP;
            var clear = null;

            if (value.match(decimalSepRex(dSeparator))) {
              clear = value.match(decimalRex(dSeparator))
                      .join("").match(clearRex(dSeparator));
              clear = clear ? clear[0].replace(dSeparator, ".") : null;
            }
            else if (value.match(decimalSepRex("."))) {
              clear = value.match(decimalRex("."))
                      .join("").match(clearRex("."));
              clear = clear ? clear[0] : null;
            }
            else {
              clear = value.match(/\d/g);
              clear = clear ? clear.join("") : null;
            }

            return clear;
          }

          ngModel.$parsers.push(function (viewValue) {
            cVal = clearValue(viewValue);
            return parseFloat(cVal);
          });

          element.on("blur", function () {
            element.val($filter('currency')(ngModel.$modelValue));
            scope.$apply();
          });

          ngModel.$formatters.unshift(function (value) {
            return $filter('currency')(value);
          });

          scope.$watch(function () {
            return ngModel.$modelValue;
          }, function (newValue, oldValue) {
            runValidations(newValue);
          });

          function runValidations(cVal) {
            if (!scope.ngRequired && isNaN(cVal)) {
              return;
            }
            if (scope.min) {
              var min = parseFloat(scope.min);
              ngModel.$setValidity('min', cVal >= min);
            }
            if (scope.max) {
              var max = parseFloat(scope.max);
              ngModel.$setValidity('max', cVal <= max);
            }
          }
        }
      }
    })

【问题讨论】:

  • 更多信息会很棒。也许是您的过滤器代码以及您如何显示字段值?
  • @Itmar - 是的,我没有付出太多。我认为这与更新前查看 $modelValue 的过滤器/指令有关。我将修改问题以包含指令。

标签: angularjs filter currency directive


【解决方案1】:
element.on("blur", function () {
        element.val($filter('currency')(ngModel.$modelValue));
        scope.$apply();
      });

我假设正在发生的事情是您正在更改一个字段并离开它,这会导致摘要循环触发 - 这使得您的事件回调中的 scope.$apply() 尝试在它已经被执行时执行.解决此问题的方法通常是将整个调用包装在 $timeout 中。

element.on("blur", function () {
        $timeout(function() {
             element.val($filter('currency')(ngModel.$modelValue));
             scope.$apply();
        });
      });

我很确定,当这种情况发生时,控制台会显示某种错误消息 - 以供将来参考。

您是否有任何理由不直接在模型上使用过滤器,例如:{{ my.model |货币 }} 而不是添加事件?似乎是不好的做法。

【讨论】:

  • 不产生错误。我无法将过滤器放在模型上,因为我正在使用用于显示的文本字段和模型中的数值。如果需要,我准备采用完全不同的方法 - 但我需要在后端显示货币和数值。
  • 您建议的代码确实出错:未捕获的 ReferenceError: $timeout 未定义 - 但我同意您的观点,即问题出在该部分。 ngModel.$modelValue 正在拉取预先更新的值,因为模型在角度处理模糊之前不会更新 - 这发生在 DOM 事件触发之后。问题是,我在哪里可以获取更新前的值?
  • 你需要注入 $compile... 你注入 $filter 和 $locale 的地方:.directive('ngCurrency', function ($filter, $locale, $compile) {
  • 完全没有改变。如果该字段退出太快,则会显示先前的值。如果您随后重新输入并离开该字段,则显示将调整为正确的(模型)值。
  • 你能创建一个 plunkr 吗?
猜你喜欢
  • 1970-01-01
  • 2018-12-28
  • 2015-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-06
相关资源
最近更新 更多