【问题标题】:ngModel $formatters not being invokedngModel $formatters 没有被调用
【发布时间】:2014-10-08 01:21:37
【问题描述】:

我想知道为什么我的 $parsers 被调用但我的 $formatters 没有被调用。我修改了Custom Control Example 中的 plunker 以包含 $parsers 和 $formatters。看起来我的 $parsers 正在被调用,但我的 $formatters 没有被调用。我是否错误地使用了 $parsers 和/或 $formatters?这是我修改后的 plunker:http://plnkr.co/edit/o1EM05AtDGw2OMDwv9dR.

angular.module('customControl', ['ngSanitize']).
  directive('contenteditable', ['$sce', function($sce) {
    return {
      restrict: 'A', // only activate on element attribute
      require: '?ngModel', // get a hold of NgModelController
      link: function(scope, element, attrs, ngModel) {
        if (!ngModel) return; // do nothing if no ng-model

        // Specify how UI should be updated
        ngModel.$render = function() {
          element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
        };

        ngModel.$parsers.push(function (viewValue) {
          console.log("parsing");
          return viewValue + "_extra_model_stuff";
        });

        ngModel.$formatters.push(function (modelValue) {
          console.log("never formats : (");
          return modelValue + "_formatted_view_stuff";
        });

        // Listen for change events to enable binding
        element.on('blur keyup change', function() {
          scope.$apply(read);
        });
        read(); // initialize

        // Write data to the model
        function read() {
          var html = element.html();
          // When we clear the content editable the browser leaves a <br> behind
          // If strip-br attribute is provided then we strip this out
          if ( attrs.stripBr && html == '<br>' ) {
            html = '';
          }
          ngModel.$setViewValue(html);
        }
      }
    };
  }]);

在仔细检查 angular.js 之后,看起来 ctrl 引用了一个 ngModelController。我希望它指的是我将格式化程序附加到的 ngModelController。但是,它 ctrl.$formatters 是一个空数组,所以这必须是一个不同的 ngModelController。我不明白为什么。

$scope.$watch(function ngModelWatch() {
  var modelValue = ngModelGet();

  // if scope model value and ngModel value are out of sync
  // TODO(perf): why not move this to the action fn?
  if (modelValue !== ctrl.$modelValue) {
    ctrl.$modelValue = modelValue;

    var formatters = ctrl.$formatters,
        idx = formatters.length;

    var viewValue = modelValue;
    while(idx--) {
      viewValue = formatters[idx](viewValue);
    }
    if (ctrl.$viewValue !== viewValue) {
      ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
      ctrl.$render();

      ctrl.$$runValidators(undefined, modelValue, viewValue, noop);
    }
  }

  return modelValue;
});

【问题讨论】:

  • 格式化程序 is 在您的 Plunker 中调用。
  • @zeroflagL 你看到never formats : (" 被记录了吗?我不。我正在使用 Chrome 37.0.2062.124。
  • 是的,每当我更改 textarea 中的文本时都会这样做。
  • @zeroflagL 好的,我只是在编辑指令呈现的 div。我想我不明白何时调用 $parser 和 $formatter 。我已经阅读了角度文档,但我一定遗漏了一些东西,因为我不明白何时/为什么调用 $formatters。您介意解释一下何时以及为什么为此示例专门调用了 $formatters 吗?谢谢!
  • 当模型改变并且必须渲染时调用格式化程序。当 UI 表示发生更改并且必须更新模型时,将调用解析器。当您编辑 contenteditable 时,您会更改 UI 表示,因此会调用解析器并更新模型。当您编辑文本区域时,首先会发生同样的情况。但是contenteditable 仍然显示旧模型值。所以必须调用格式化程序来显示新的格式化程序。

标签: angularjs angular-ngmodel


【解决方案1】:

如上所述:

当模型改变并且必须渲染时调用格式化程序。当 UI 表示发生更改并且必须更新模型时,将调用解析器。当您编辑 contenteditable 时,您会更改 UI 表示,因此会调用解析器并更新模型。当您编辑文本区域时,首先会发生同样的情况。但是 contenteditable 仍然显示旧模型值。所以必须调用格式化程序来显示新的格式化程序。

解析器被调用,但它自己的,而不是你的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 2019-03-31
    • 2012-12-16
    相关资源
    最近更新 更多