我正在尝试实现英寸到毫米转换器...我想要的是,如果用户在文本框中输入英寸值,则文本框(视图)应以英寸显示值。模型应以毫米为单位保存该值。为此,我编写了如下所示的指令。

正如我通过调试检查的那样,该模型以毫米为单位更新。
但是,当我在文本框外单击(模糊事件)时,将视图切换到Web应用程序中的其他选项卡,然后返回,则模型值将再次填充到文本框中。因此,我认为在焦点事件上,我可以将$ modelValue / 25(毫米到英寸转换)作为参数传递给$ setViewValue()函数。但是我得到$ modelValue属性为未定义。

.directive('metricImperialInput', function($timeout){
              return{
                  require: 'ngModel',
                  link: function(scope, element, attrs, modelCtrl){
                      element.bind("focus", function(e) {
                      $timeout(function() {
                          modelCtrl.$setViewValue(modelCtrl.$modelValue/25);
                          modelCtrl.$render();
                     }, 0);
                   });
                      modelCtrl.$parsers.push(function(inputValue){
                          var changedOutput = parseInt(inputValue) * 25;
                          modelCtrl.$setViewValue(parseInt(inputValue));
                          modelCtrl.$render();
                          return parseInt(changedOutput);
                      });
                  }
              };
          });

最佳答案

您正确使用了ngModelController.$parsers,但是在解析器内部您也使用了$setViewValue(),因为解析器函数接收到的inputValue已经是$viewValue,所以完全不需要。这样可以将其与$render()一起删除。焦点事件也是不必要的,因为如果正确使用$ parsers,它不会做任何有用的事情。

因此,现在剩下的就是:

.directive('metricImperialInput', function($timeout){
          return{
              require: 'ngModel',
              link: function(scope, element, attrs, modelCtrl){
                modelCtrl.$parsers.push(function(inputValue){
                  var changedOutput = parseInt(inputValue) * 25;
                  return parseInt(changedOutput) || 0;
                });
              }
          };
      });


但这是有问题的,在开始使用输入之前,初始的$ modelValue不会转换。为此,我添加了以下几行以确保在加载指令时它将正确设置初始值,然后解析器将处理所有内容。

var initVal = $parse(attrs.ngModel)(scope);
modelCtrl.$viewValue = initVal / 25;
modelCtrl.$modelValue = initVal;
modelCtrl.$render();


您可以在此JSFiddle中找到整个解决方案。

07-28 05:35