我正在尝试实现英寸到毫米转换器...我想要的是,如果用户在文本框中输入英寸值,则文本框(视图)应以英寸显示值。模型应以毫米为单位保存该值。为此,我编写了如下所示的指令。
正如我通过调试检查的那样,该模型以毫米为单位更新。
但是,当我在文本框外单击(模糊事件)时,将视图切换到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中找到整个解决方案。