programing

AngularJS - 모델 값을 변경하는 지시에서 $render를 호출해야 하는 이유는 무엇입니까?

goodsources 2023. 10. 13. 22:05
반응형

AngularJS - 모델 값을 변경하는 지시에서 $render를 호출해야 하는 이유는 무엇입니까?

ngModel 명령어를 사용하여 요소에 부착되도록 설계된 명령어를 만들었습니다.모델의 값이 일치하는 경우 값을 이전 값으로 설정해야 합니다.예를 들어 "foo"를 찾고 있는데, 입력된 내용이면 이전으로 다시 설정합니다.

모델 값만 보고 있기 때문에 제 유닛 테스트는 잘 통과되었습니다.그러나 실제로는 "되돌리기"가 트리거되면 DOM이 업데이트되지 않습니다.여기서 우리가 추측할 수 있는 것은 오래된 == 새로 설정하면 더티 체크가 발생하지 않는다는 것입니다.$setViewValue 방법을 사용해봤는데, 해야 할 일을 하고 있는 것 같습니다.그러나 ngModel이라고 명시적으로 부를 때까지 DOM(그리고 브라우저에 보이는 것)을 업데이트하지 않습니다.새 값을 설정한 후 $render().잘 작동하지만 더 적절한 방법이 있는지 알고 싶습니다.

코드는 아래에 있고, 여기 그것에 대한 연주가 있습니다.

angular.module('myDirective', [])
    .directive('myDirective', function () {
    return {
        restrict: 'A',
        terminal: true,
        require: "?ngModel",
        link: function (scope, element, attrs, ngModel) {
            scope.$watch(attrs.ngModel, function (newValue, oldValue) {
                //ngModel.$setViewValue(newValue + "!");   

                if (newValue == "foo")
                {
                    ngModel.$setViewValue(oldValue);   
                    /* 
                        I Need this render call in order to update the input box; is that OK?
                        My best guess is that setting new = old prevents a dirty check which would trigger $render()
                    */
                    ngModel.$render();
                }
            });
        }
    };
});

function x($scope) {
    $scope.test = 'value here';
}

여기서 가장 좋은 추측은 오래된 == 새로 설정하면 더티 체크가 발생하지 않는다는 것입니다.

감시자 수신자는 수신 중인 표현식의 값이 변경될 때만 호출됩니다.하지만 모델을 원래 값으로 다시 바꾸셨기 때문에 값이 전혀 변하지 않은 것과 같아서 다시 호출되지는 않을 것입니다.그러나 주의해야 할 점은 동일한 속성이 무한 루프를 초래할 수 있다는 감시자 내부의 속성 값을 변경하는 것입니다.

그러나 ngModel이라고 명시적으로 부를 때까지 DOM(그리고 브라우저에 보이는 것)을 업데이트하지 않습니다.새 값을 설정한 후 $render().

맞습니다.$setViewValue모델 값을 보기에 의해 업데이트된 것처럼 설정하지만 호출해야 합니다.$render(새) 모델 값을 기반으로 뷰를 효과적으로 렌더링합니다.자세한 내용은 이 토론을 확인하시기 바랍니다.

마지막으로, 당신의 문제를 다른 방식으로 접근해야 한다고 생각합니다.당신은 사용할 수 있습니다.$parsers의 소유물.NgModelControllerWatcher를 사용하는 대신 사용자 입력을 확인합니다.

link: function (scope, element, attrs, ngModel) {
  if (!ngModel) return;

  ngModel.$parsers.unshift(function(viewValue) {
    if(viewValue === 'foo') {                 
      var currentValue = ngModel.$modelValue;
      ngModel.$setViewValue(currentValue);
      ngModel.$render(); 
      return currentValue;
    }
    else 
      return viewValue;
  });
}

위의 코드를 사용하기 위해 jsFiddle 스크립트를 변경했습니다.

angular.module('myDirective', [])
.directive('myDirective', function () {
  return {
    restrict: 'A',
    terminal: true,
    require: "?ngModel",
    link: function (scope, element, attrs, ngModel) {
      if (!ngModel) return;

      ngModel.$parsers.unshift(function(viewValue) {
        if(viewValue === 'foo') {                 
          var currentValue = ngModel.$modelValue;
          ngModel.$setViewValue(currentValue);
          ngModel.$render(); 
          return currentValue;
        }
        else 
          return viewValue;
      });
    }
  };
});

function x($scope) {
  $scope.test = 'value here';
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<h1>Foo Fighter</h1>
I hate "foo", just try and type it in the box.
<div ng-app="myDirective" ng-controller="x">
  <input type="text" ng-model="test" my-directive>
  <br />
  model: {{test}}
</div>

언급URL : https://stackoverflow.com/questions/19167517/angularjs-in-a-directive-that-changes-the-model-value-why-do-i-have-to-call

반응형