【问题标题】:$parsers and $formatters are being called only once, instead of on every value update$parsers 和 $formatters 只被调用一次,而不是在每次值更新时
【发布时间】:2017-05-06 14:27:25
【问题描述】:

我正在尝试创建一个名为currency 的指令,该指令在输入文本之前附加一个$。美元符号应始终显示且不可移除。

这是我的代码:

app.directive('currency', function() {
    return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, elem, attrs, controller) {

      // view -> model
      controller.$parsers.push(function (viewValue) {
        viewValue = viewValue.replace(/^\$/, '');
        controller.$viewValue = viewValue;
        return viewValue;
      });

      // model -> view
      controller.$formatters.push(function (modelValue) {
        modelValue = '$' + modelValue;
        controller.$modelValue = modelValue;
        return modelValue;
      });
    }
  };
});

工作示例:https://jsfiddle.net/U3pVM/29012/

如您所见,美元符号最初是附加的,但可以删除,之后不会附加。我推送到$formatters 的函数似乎只被调用一次。它应该像那样工作还是我错过了什么?如何实现所需的行为?

【问题讨论】:

  • 如果您在输入字段中输入,您将触发 $parsers 而不是 $formatters。您可以通过添加操作相同 ngModel 的第二个输入字段来测试这一点。例如jsfiddle.net/U3pVM/29013
  • 在视图中更改模型时不会调用格式化程序

标签: javascript angularjs ecmascript-5


【解决方案1】:

好的,我尝试了一种解决方法,它有效,但我不确定这是否是正确的方法。

更新小提琴:https://jsfiddle.net/U3pVM/29014/

controller.$parsers.push(function (viewValue) {
      //console.log(viewValue.substring(0,1));

      if(viewValue.substring(0,1) != "$"){
            var view_value = "$" + viewValue;
          controller.$setViewValue(view_value);
          controller.$render();
      }
        viewValue = viewValue.replace(/^\$/, '');
        //controller.$viewValue = viewValue;


        console.log(viewValue);
        return viewValue;
      });

P.S:我不知道你为什么在你的link 函数中注入ngModel 作为controller。这可能是一个错误。

【讨论】:

    【解决方案2】:

    我认为您不太了解 $parsers 和 $formatters 的作用。每当您在输入字段中输入内容时,$parsers 负责将此值转换为模型值。格式化程序负责将模型值转换为输入字段中的显示值。

    当有人在字段中输入内容($parser 功能)时,您尝试更改输入字段的内容($formatter 功能)。

    虽然我确信有一些变通方法可以让它以这种方式工作,但是当你这样做时,你误用了 $parsers 和 $formatters 的概念。相反,您应该查看一个自定义指令(或扩展您拥有的指令)以添加到执行您想要执行的操作的输入中,例如通过处理 keyups。

    编辑

    请参阅以下链接函数的代码示例,以了解我的意思:

    link: function (scope, elem, attrs, controller) {
    
      elem.bind('keyup', function(evt) {
         // Change the displayed value after every keypress
         // This function is an example and needs serious work...
         // Perhaps you should even put this in a separate directive
         var value = elem.val().replace(/[^$0-9]/g, '');
         if (value && value.substring(0,1) !== '$') {
            value = '$' + value;
         }
         elem.val(value);
      });
    
      // view -> model
      controller.$parsers.push(function (viewValue) {
        // Any time the view changes, remove the $ sign and interpret the rest as number for the model
        var modelValue = viewValue.replace(/^\$/, '');
        return parseFloat(modelValue);
      });
    
      // model -> view
      controller.$formatters.push(function (modelValue) {
        // Any time the model (number) changes, append it with a $ sign for the view
        var viewValue = '$' + modelValue;
        return viewValue;
      });
    }
    

    或者检查整个小提琴:https://jsfiddle.net/cL0hpvp4/

    【讨论】:

    • 想展示一个例子吗?如果我将$ 附加到输入值,它将存储在模型中,对吗?我不希望这样,只需要更改显示的值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多