我有一些自定义验证代码,其中包括$ formatter。(为了正确起见,我将货币以便士存储,但以磅为便士显示。)
如果用户在输入中键入“ 10”(这是一个有效值),则输入移至下一个字段后,输入仍显示“ 10”。
我希望它显示10.00以保持一致性。
如果模型将值更改为1000,那么格式化程序将使该字段显示为“ 10.00”。
我希望格式化程序在field.blur()上运行(只要输入有效)。
我的问题是,如果将模型值从10更改为10,可以理解的是没有更改,因此该字段不会重新呈现。
码:
var CURRENCY_REGEXP = /^\-?\d+(\.?\d?\d?)?$/; app.directive('currency', function() { return { require: 'ngModel', link: function(scope, elm, attrs, ctrl) { ctrl.$parsers.unshift(function(viewValue) { if (CURRENCY_REGEXP.test(viewValue)) { // it is valid ctrl.$setValidity('currency', true); console.log("valid"); return viewValue * 100; } else if (viewValue === '') { return 0; } else { // it is invalid, return undefined (no model update) ctrl.$setValidity('currency', false); console.log("invalid"); return undefined; } }); ctrl.$formatters.push(function(modelValue) { if (modelValue === 0) { // we're using integer pence, so this is safe return ''; } return (modelValue / 100).toFixed(2); }); } }; });
PS这与Angular的内置“货币”无关。
更新:根据安迪的回答,我添加了一个“ renderOnBlur”指令。它被调用,但是调用render方法不会重新渲染输入。即“ 10”保持为“ 10”,而不是根据需要更改为“ 10.00”。
(当模型值在这些字段中更改时,它们将正确显示为小数点后两位。)
Andy提到的页面http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController说您必须实现$render自己。这似乎很奇怪,因为当模型值更改时,输入已经正确呈现。
$render
app.directive('renderOnBlur', function() { return { require: 'ngModel', restrict: 'A', link: function(scope, elm, attrs, ctrl) { elm.bind('blur', function() { console.log('rendering ctrl', ctrl); ctrl.$render(); }); } }; });
PS:我不知道该怎么办restrict: 'A',-在最糟糕的情况下,这是真正的“货神教”式编程。该require: 'ngModel',填充似乎是必要ctrl的参数。
restrict: 'A',
require: 'ngModel',
ctrl
受@Dan Doyen的回答启发,我将其重写为:
app.directive('renderOnBlur', function() { return { require: 'ngModel', restrict: 'A', link: function(scope, elm, attrs, ctrl) { elm.bind('blur', function() { var viewValue = ctrl.$modelValue; for (var i in ctrl.$formatters) { viewValue = ctrl.$formatters[i](viewValue); } ctrl.$viewValue = viewValue; ctrl.$render(); }); } }; });
这具有对任何$ formatter通用的好处,而不是像Dan的回答那样重复格式化程序代码。
您的控制器的$ modelValue正在正确更新,但是,由于blur事件发生在angular之外,因此您的$ viewValue似乎没有。这个怎么样?
elm.bind('blur', function() { ctrl.$viewValue = (ctrl.$modelValue / 100).toFixed(2); ctrl.$render(); });