AngularJS如何强制输入在模糊时重新渲染

fad*_*bee 23 angularjs

我有一些自定义验证代码,其中包含$ formatter.(我以便士的形式存储货币以获得正确性,但以磅为单位显示.)

如果用户在输入中键入"10"(这是一个有效值),则输入在移动到下一个字段后仍然显示"10".

我希望它显示10.00的一致性.

如果模型将值更改为1000,则格式化程序将使字段显示为'10 .00'.

我希望formatter在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); 
      });
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

PS这与Angular的内置"货币"无关.


更新:根据Andy的回答,我添加了'renderOnBlur'指令.它被调用,但调用render方法不会重新呈现输入.即'10'保持为'10',而不是根据需要改为'10 .00'.

(当模型值在这些字段中更改时,它们将使用2个小数位正确呈现.)

Andy提到的页面http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController说你必须$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();
            });
        }
    };  
});
Run Code Online (Sandbox Code Playgroud)

PS我不知道是什么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();
            });
        }
    };  
});
Run Code Online (Sandbox Code Playgroud)

这样做的好处是对任何$ formatter都是通用的,而不是像Dan的回答那样重复格式化代码.

Dan*_*yon 14

但是,你的控制器的$ modelValue正在正确更新,但由于模糊事件发生在angular之外,看起来你的$ viewValue不是.这个怎么样?

 elm.bind('blur', function() {
       ctrl.$viewValue = (ctrl.$modelValue / 100).toFixed(2);
       ctrl.$render();
 });
Run Code Online (Sandbox Code Playgroud)