AngularJS how to force an input to be re-rendered on blur

前端 未结 5 1604
攒了一身酷
攒了一身酷 2020-12-24 14:17

I have some custom validation code, which includes a $formatter. (I store currency in pence for correctness, but display in pounds.pence.)

If the user types \'10\'

相关标签:
5条回答
  • 2020-12-24 14:51

    A little improved: Do not reformat if the value is not valid (in my case invalid text just got cleared on blur, which is bad for usability, I think).

    Also, like Dark Falcon said: Formatters should be iterated backwards.

    Finally do not iterate over arrays with for-in, at least not without checking hasOwnProperty() (for me the code crashed because it treated Array.find() as a formatter).

    // Reformat text on blur
    elements.bind('blur', function() {
        if(!ngModel.$valid) {
            return;
        }
        var viewValue = ngModel.$modelValue;
        var formatters = ngModel.$formatters;
        for (var i = formatters.length - 1; i >= 0; --i) {
            viewValue = formatters[i](viewValue);
        }
        ngModel.$viewValue = viewValue;
        ngModel.$render();
    });
    
    0 讨论(0)
  • Try using ctrl.$render on blur.

    elm.bind('blur', function() { ctrl.$render() });

    See it in http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController.

    0 讨论(0)
  • 2020-12-24 14:58

    Your controller's $modelValue is being updated properly, however, but since the blur event is happening outside of angular, it seems your $viewValue is not. How about this?

     elm.bind('blur', function() {
           ctrl.$viewValue = (ctrl.$modelValue / 100).toFixed(2);
           ctrl.$render();
     });
    
    0 讨论(0)
  • 2020-12-24 14:58

    An alternative implementation is to trigger angular's formatters. Angular 1.5 implementation watches $modelValue for changes, and then triggers $formatters. To do this manually, one can do this

    function triggerFormattersAndRender(ngModel, scope) {
      /* Triggers angulars formatters, which watches for $modelValue changes */
      var originalModelValue = ngModel.$modelValue;
      if (originalModelValue === null) return;
    
      ngModel.$modelValue = null;
      scope.$digest();
      ngModel.$modelValue = originalModelValue;
      scope.$digest();
    }
    

    And then in the directive

    function link(scope, elem, attrs, ngModel) {
    
        elem.bind('blur', function() {
            triggerFormattersAndRender(ngModel, scope);
        });
    
        // when we get focus, display full precision
        elem.bind('focus', function() {
          if (ngModel.$modelValue) {
            ngModel.$setViewValue(ngModel.$modelValue.toString());
            ngModel.$render();
          }
        })
    
    }
    
    0 讨论(0)
  • 2020-12-24 14:58

    10.00 === 10 true

    a=10.00

    console.log(a) 10

    .00 don't means anything on javascript, because of this your 10.00 are becoming 10

    I suggest to make the value a String so you can create the format that you want

    0 讨论(0)
提交回复
热议问题