programing

커스텀 디렉티브에 Angular Validation 디렉티브를 프로그래밍 방식으로 적용할 수 있습니까?

lastmoon 2023. 3. 23. 23:04
반응형

커스텀 디렉티브에 Angular Validation 디렉티브를 프로그래밍 방식으로 적용할 수 있습니까?

html 입력에는 다음과 같은 패턴이 많이 있습니다.이것은 전화번호입니다.

<input type="text" ng-model="CellPhoneNumber" required ng-pattern="/^[0-9]+$/" ng-minlength="10" />

적용되는 위치에 따라 Angular에게 다음 세 가지 규칙을 모두 적용하도록 지시하는 커스텀 디렉티브를 만들고 싶습니다.

<input type="text" ng-model="CellPhoneNumber" bk-ng-validation="phoneNumber"/>

그런 다음, 내 지시어의 코드가 다음 함수를 찾아 호출합니다.phoneNumber예를 들어 다음과 같은 것을 보고 싶습니다.

리스트 1:

function bkNgPhoneNumber(model) {
    // This is purely SPECULATIVE pseudo-code, just to convey an idea.
    model.errors.add(applyMinLength(10, model));
    model.errors.add(applyMaxLength(15, model));
    model.errors.add(applyPattern("/^[0-9]+$/", model));
}

이러한 규칙에 대한 코드 재작성보다 위의 접근 방식을 선호합니다. 예를 들어 다음과 같습니다.

리스트 2:

function phoneNumber(model) {
    if (model.length < 10 || model.length > 15) {
        model.errors.add("Must be 10 to 15 chars!");
    }
}

모든 속성 기반 지시어를 없애고 싶지는 않지만 목록 1 코드를 호출하는 '매크로' 지시어를 만드는 것이 좋습니다. 이 명령어는 일련의 더 많은 '마이크로' 유효성 검사를 인턴으로 호출합니다.

이를 위한 한 가지 방법(즉, 코드를 다시 작성하지 않고 기존 검증자를 적용)은 검증 지침의 각 속성을 추가하고 재컴파일을 강제하는 것이다.이를 위해서는 지시가 높은 우선 순위를 가져야 하며, 또한terminal: true.

app.directive("bkNgValidation", function($compile){
  return {
    priority: 10000,
    terminal: true,
    link: function(scope, element){
      element.attr("ng-required", "true");
      element.attr("ng-minlength", 20);
      element.attr("ng-maxlength", 30);

      // prevent infinite loop
      element.removeAttr("bk-ng-validation");

      $compile(element)(scope);
    }
  };
});

데모

더 많은 검증을 사용하는 경우 제한 없이 요소를 식별하고 검증하는 서비스를 생성할 수 있습니다.angular의 기본 지시어는 그대로입니다.

예를 들어:

    module.service('$Validation', ["$compile",function($compile){

        this.validators = {
            'phoneNumber': [['required', 1], ['minlength',6], ['maxlength', 10], ['pattern', /^[0-9]+$/.source]],
            'phoneNumber2Custom': function(value){ 
                return /^[0-9]{6,10}$/.test(value) 
            },
            'userTwitter': function(value){
                return /^@(.+)/.test(value)
            }
            // ...etc... /
        }

        this.add = function(scope, element, attrs, model){
            var name = attrs.bkNgValidation, type;
            if(!(type = this.validators[name])) return;
            else if(angular.isFunction(type)) return (model.$validators[name] = type);

            element.removeAttr("bk-ng-validation");
            angular.forEach(type, function(expr){
                element.attr(expr[0], expr[1])
            });
            $compile(element)(scope)        
        };

    }]).directive('bkNgValidation', ["$Validation", function ($Validation) {
        return {
            require: '?ngModel',
            priority: 1e5,
            link: function(){
                $Validation.add.apply($Validation, arguments);
            }
        }
    }])

데모

다음과 같은 방법을 사용할 수 있습니다.

.directive('bkNgValidation', function () {
  return: {
    link: function (scope, element, attrs) {
      if (attrs['bk-ng-validation'] === 'phoneNumber') {
       element.$validateModel(function (value, validator) {
         if (value.length < 10 || value.length > 15) {
           validator.$setValidity('phone', true);
         } else {
           validator.$setValidity('phone', false);
         }
       });
      }
    }
  }
})

필요한 모든 검증자를 통한 제어를 포함하는 새 구성 요소를 생성할 수 있습니다.구성 요소는 다음과 같습니다.

<my-control name="field" ng-model="text"></my-control>

필요한 논리 컴포넌트는 모두 내부에 보관해야 합니다.그러기 위해서는my-controldirective를 지정합니다.템플릿 내부에는 다음과 같은 검증 속성을 가진 입력을 배치할 수 있습니다.

<input type="text" ng-model="value" class="form-control" ng-pattern="'^(?!ng-*)'" minlength="3">

그런 다음 컴포넌트에서 ng-model 값을 바인드하여 다음과 같이 입력해야 합니다.

angular.module('app', []).directive('myControl', function() {
   return {
       restrict: 'E',
       require: 'ngModel', //import ngModel into linking function
       templateUrl: 'myControl.tpl',
       scope: {}, //our component can have private properties, isolate it
       link: function(scope, elm, attrs, ngModel) {
           // reflect model changes via js
           ngModel.$render = function() {
               scope.value = ngModel.$viewValue;
           };
           // update model value after changes in input
           scope.$watch('value', function(value) {
               ngModel.$setViewValue(value);
           });
       }
   };
});

다음은 이 컴포넌트의 동작과 작동 방식을 보여 주는 데모입니다.

지시문은 유지하기가 그만큼 힘들다고 가정하고 요소에 따라 필요한 모든 검증을 제공하기 위해 지시문을 유지하려고 하기 때문에 반대 방향으로 가고 있습니다.

흥미로운 접근법이긴 하지만 이 접근법의 모듈화에 대해 주의를 기울여야 합니다. 즉, 이 많은 노력을 하나의 지침에만 할당하는 것은 "순수한 각도 방식"을 사용하여 작업을 수행하는 모범 사례에 반하는 것입니다.

계속 꼭 권합니다.ngModelController(각도주입할 수 있는 JS Docs) 속성link()하나의 지시어의 기능.더 정확히 말하면, '우리'는요.$validators.

개 요?$validatorsNgModel 컨 ng ng ng ng ng ng ng 。

검증 중에 부울을 반환하는 요소에 대한 유효성을 설정/해제할 수 있습니다.

app.directive('validator', function () {
    var definition = {
        restrict: 'A',
        require: '?ngModel',
        link: function (scope, element, attrs, ngModel) {
            // Return if no ngModelController
            if (!ngModel) {
                return;
            }

            ngModel.$validators.validateLength = function (modelValue, viewValue) {
                // modelValue === the value of the ngModel, on the script side
                // viewValue === the value of the ngModel, on the HTML (rendered) side
                // 
                // you can set-up $parsers, $formatters, $validators, etc, to handle the element

                return !(modelValue.length > 20);
            }
        }
    };

    return definition;
});

이 구현에 대한 자세한 내용을 읽어보시길 권장합니다. 왜냐하면 특정 조작은 다음 동작의 흐름을 방해할 수 있기 때문입니다.$digest이치노

편집 1:

제가 댓글에 언급했듯이, 여기 작동하는 예를 든 플렁커가 있습니다.

언급URL : https://stackoverflow.com/questions/30149924/can-i-programmatically-apply-angular-validation-directives-inside-a-custom-direc

반응형