IT

AngularJs 블러에서 입력을 다시 렌더링하도록 강제하는 방법

itgroup 2023. 10. 20. 13:34
반응형

AngularJs 블러에서 입력을 다시 렌더링하도록 강제하는 방법

저는 $포맷이 포함된 커스텀 검증 코드를 가지고 있습니다.(나는 정확성을 위해 통화를 펜스 단위로 저장하지만 파운드 단위로 표시합니다.펜스.)

사용자가 입력에 '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); 
      });
    }
  };
});

추신: 이건 앵귤러의 내장된 '통화'와는 아무 상관이 없습니다.


업데이트: Andy의 답변대로 'renderOnBlur' 지침을 추가했습니다.호출되지만 렌더 메서드를 호출해도 입력이 다시 렌더링되지 않습니다. 즉 '10'은 원하는 대로 '10.00'으로 변경되지 않고 '10'으로 유지됩니다.

(이 필드에서 모형 값이 변경되면 소수점 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();
            });
        }
    };  
});

P.S. 무슨 일인지 전혀 모르겠습니다.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();
            });
        }
    };  
});

이것은 Dan의 답변처럼 형식 코드를 반복하는 것이 아니라 모든 $ 형식에 대해 일반적으로 사용할 수 있는 장점이 있습니다.

컨트롤러의 $modelValue가 올바르게 업데이트되고 있지만 블러 이벤트가 각도를 벗어나 발생하므로 $viewValue가 그렇지 않은 것 같습니다.이건 어때?

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

약간의 개선:값이 올바르지 않으면 다시 포맷하지 마십시오(제 경우에는 잘못된 텍스트가 블러에서 지워져서 사용성에 좋지 않은 것 같습니다).

또한 다크 팰컨이 말한 것처럼.포맷터는 뒤로 반복해야 합니다.

마지막으로, 적어도 hasOwnProperty()를 확인하지 않고는 for-in이 있는 어레이를 반복하지 마십시오(저의 경우 Array.find()를 포맷으로 처리했기 때문에 코드가 충돌했습니다).

// 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();
});

대안적인 구현은 각도의 형식을 트리거하는 것입니다.Angular 1.5 구현은 $modelValue에서 변경 사항을 확인한 다음 $formatter를 트리거합니다.수동으로 하려면 이렇게 하면 됩니다.

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();
}

그리고 그 지시에 따라

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();
      }
    })

}

ctrl을 사용해 봅니다.흐릿한 부분에 $ render.

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

http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController 에서 확인하세요.

10.00 === 10진실의

a=10.00

console.log(a) 10

.00은 자바스크립트에서 아무 의미가 없습니다. 이것 때문에 당신의 10.00은 10이 되고 있습니다.

당신이 원하는 포맷을 만들 수 있도록 값을 String으로 하는 것을 제안합니다.

언급URL : https://stackoverflow.com/questions/11380866/angularjs-how-to-force-an-input-to-be-re-rendered-on-blur

반응형