AngularJS 양식에 사용자 정의 유효성 검사를 추가하는 방법은 무엇입니까?


278

required속성 등 을 추가하여 입력 필드 및 유효성 검사 설정이있는 양식이 있습니다 . 그러나 일부 필드의 경우 추가 검증이 필요합니다. FormController제어 하는 유효성 검사를 어떻게 "탭핑" 합니까?

사용자 지정 유효성 검사는 "이 3 개의 필드가 채워지면이 필드가 필요하며 특정 방식으로 형식을 지정해야합니다"와 같은 것일 수 있습니다.

메소드가 FormController.$setValidity있지만 공개 API처럼 보이지 않으므로 오히려 사용하지 않습니다. 사용자 지정 지시문을 만들고 사용하는 NgModelController것은 다른 옵션처럼 보이지만 기본적으로 원하지 않는 각 사용자 지정 유효성 검사 규칙에 대한 지시문을 만들어야합니다.

실제로 컨트롤러에서 필드를 유효하지 않은 FormController것으로 표시하는 것은 (동기화 상태를 유지하는 동안 ) 가장 간단한 시나리오에서 작업을 수행하는 데 필요한 것일 수도 있지만 그렇게하는 방법을 모르겠습니다.


4
각도 JS에서 사용자 지정 유효성 검사를 처리하는 데 필요한 괴물 코딩에 대한 좋은 기사가 있습니다. 확인 밖으로
Anshu

맞춤 지시문이 필요하기 때문에 정확히 내가 원하는 것은 아니지만 어쨌든 좋은 기사이므로 귀하의 답변을 수락합니다.
botteaap

나는 똑같은 것을 궁금해한다. 나는 FormController 수준의 제어를 좋아한다. 예를 들어, 특정 사용자 지정 지시문이 FormController 인스턴스를와 같은 것으로 플래그 지정하고 싶습니다 formName.$warning.
Adam Waselnuk

2
나는 그것이 $$공개되지 않은 공개 API보다 우선 한다고 생각합니다 $. 참조 stackoverflow.com/questions/19338493/...
다니엘 F

답변:


370

편집 : 아래에 ngMessages (> = 1.3.X)에 대한 정보가 추가되었습니다.

표준 양식 유효성 검사 메시지 (1.0.X 이상)

Google "Angular Form Validation"인 경우 이것이 최고의 결과 중 하나이므로 현재 거기에서 오는 사람을 위해 다른 답변을 추가하고 싶습니다.

FormController. $ setValidity에는 메소드가 있지만 공용 API처럼 보이지 않으므로 사용하지는 않습니다.

"공개"이며 걱정할 필요가 없습니다. 그걸 써. 그게 다야. 그것이 사용되지 않았다면, Angular 개발자들은 그것을 폐쇄하여 민영화했을 것입니다.

사용자 정의 유효성 검사를 수행하기 위해 Angular-UI를 다른 대답으로 제안하지 않으려면 자체 유효성 검사 지시문을 롤백하면됩니다.

app.directive('blacklist', function (){ 
   return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
          var blacklist = attr.blacklist.split(',');

          //For DOM -> model validation
          ngModel.$parsers.unshift(function(value) {
             var valid = blacklist.indexOf(value) === -1;
             ngModel.$setValidity('blacklist', valid);
             return valid ? value : undefined;
          });

          //For model -> DOM validation
          ngModel.$formatters.unshift(function(value) {
             ngModel.$setValidity('blacklist', blacklist.indexOf(value) === -1);
             return value;
          });
      }
   };
});

다음은 사용법 예입니다.

<form name="myForm" ng-submit="doSomething()">
   <input type="text" name="fruitName" ng-model="data.fruitName" blacklist="coconuts,bananas,pears" required/>
   <span ng-show="myForm.fruitName.$error.blacklist">
      The phrase "{{data.fruitName}}" is blacklisted</span>
   <span ng-show="myForm.fruitName.$error.required">required</span>
   <button type="submit" ng-disabled="myForm.$invalid">Submit</button>
</form>

참고 : 1.2.X에서는 아마도 위의 것을 대체 ng-if하는 것이 좋습니다.ng-show

필수 플 런커 링크 는 다음과 같습니다.

또한이 주제에 관한 블로그 항목을 조금 더 자세히 작성했습니다.

각도 형식 검증

사용자 지정 유효성 검사 지시문

편집 : 1.3.X에서 ngMessages 사용

이제 ngShow 대신 ngMessages 모듈을 사용하여 오류 메시지를 표시 할 수 있습니다. 실제로 무엇이든 작동하지만 오류 메시지 일 필요는 없지만 기본 사항은 다음과 같습니다.

  1. 포함 <script src="angular-messages.js"></script>
  2. ngMessages모듈 선언에서 참조 :

    var app = angular.module('myApp', ['ngMessages']);
  3. 적절한 마크 업을 추가하십시오.

    <form name="personForm">
      <input type="email" name="email" ng-model="person.email" required/>
    
      <div ng-messages="personForm.email.$error">
        <div ng-message="required">required</div>
        <div ng-message="email">invalid email</div>
      </div>
    </form>

위의 마크 업에서 ng-message="personForm.email.$error"기본적으로 ng-message하위 지시문 의 컨텍스트를 지정합니다. 다음 ng-message="required"ng-message="email"시계에 그 상황에 대한 속성을 지정합니다. 가장 중요한 것은 체크인 순서를 지정하는 것입니다 . 목록에서 발견 된 첫 번째 메시지는 "거대한"이기고, 그 메시지와 다른 메시지는 표시되지 않습니다.

그리고 ngMessages의 예를 들어 plunker


6
$ parsers.unshift에 전달하는 함수의 값을 반환하면 잘못된 값도 모델에 저장됩니다-정의되지 않은 값을 반환하는 것이 좋습니다 (값이 유효하지 않은 경우).
georgiosd

5
+1 @georgiosd ... 100 % 정확합니다. Angular의 기능을 살펴보면 정의되지 않은 상태로 반환됩니다. 유효하지 않은 형식의 모델이 제출되지 않기 때문에 값을 반환하는 것이 큰 도움 이되지는 않지만 ... 미안보다 안전합니다.
Ben Lesh

2
좋은 물건! Angular에서 사용자 정의 유효성 검사에 대한 훌륭한 글을 찾고자하는 경우 Google에서 @blesh가 작성한 것을 확인하십시오.
maaachine

AngularJS 및 필터를 사용하여 고급 양식 유효성 검사 를 확인 했습니까 ? 일반적으로 필터 유효성 검사를 해결합니다.
베니 보 테마

1
나는 당신이 return value ? valid : undefined위에서 해야 할 것이라고 생각합니다 .
GChorn

92

Angular-UI의 프로젝트에는 ui-validate 지시문이 포함되어 있습니다. 유효성 검사를 수행하기 위해 호출 할 함수를 지정할 수 있습니다.

데모 페이지 ( http://angular-ui.github.com/ )를 확인하고 유효성 검증 표제를 검색 하십시오 .

데모 페이지에서 :

<input ng-model="email" ui-validate='{blacklist : notBlackListed}'>
<span ng-show='form.email.$error.blacklist'>This e-mail is black-listed!</span>

그런 다음 컨트롤러에서 :

function ValidateCtrl($scope) {
  $scope.blackList = ['bad@domain.com','verybad@domain.com'];
  $scope.notBlackListed = function(value) {
    return $scope.blackList.indexOf(value) === -1;
  };
}

Angular 1.4를 사용하여 이것이 작동하지 않는다는 것이 얼마나 이상합니까?
Nick

46

유효성 검증 시나리오에 ng-required를 사용할 수 있습니다 ( "이 3 개의 필드가 채워지면이 필드가 필요합니다").

<div ng-app>
    <input type="text" ng-model="field1" placeholder="Field1">
    <input type="text" ng-model="field2" placeholder="Field2">
    <input type="text" ng-model="field3" placeholder="Field3">
    <input type="text" ng-model="dependentField" placeholder="Custom validation"
        ng-required="field1 && field2 && field3">
</div>

2
이것은 나를 위해 일했습니다. 다른 필드 값에 의존하는 간단한 유효성 검사의 경우 복잡한 유효성 검사 규칙을 작성하는 대신 이동하는 방법입니다.
VimalKumar

28

Angular-Validator를 사용할 수 있습니다 .

예 : 함수를 사용하여 필드 유효성 검사

<input  type = "text"
    name = "firstName"
    ng-model = "person.firstName"
    validator = "myCustomValidationFunction(form.firstName)">

그런 다음 컨트롤러에 다음과 같은 것이 있습니다.

$scope.myCustomValidationFunction = function(firstName){ 
   if ( firstName === "John") {
       return true;
    }

다음과 같이 할 수도 있습니다 :

<input  type = "text"
        name = "firstName"
        ng-model = "person.firstName"
        validator = "'!(field1 && field2 && field3)'"
        invalid-message = "'This field is required'">

(여기서 field1 field2 및 field3은 범위 변수입니다. 필드가 빈 문자열과 같지 않은지 확인할 수도 있습니다)

필드가 통과하지 못하면 validator필드가 유효하지 않은 것으로 표시되고 사용자는 양식을 제출할 수 없습니다.

더 많은 사용 사례와 예제는 https://github.com/turinggroup/angular-validator를 참조하십시오.

면책 조항 : 저는 Angular-Validator의 저자입니다


13

최근에 각도 형식 입력의 표현식 기반 무효화를 허용하는 지시문을 작성했습니다. 유효한 각도 식을 사용할 수 있으며 객체 표기법을 사용하여 사용자 지정 유효성 검사 키를 지원합니다. 각도 v1.3.8로 테스트

        .directive('invalidIf', [function () {
        return {
            require: 'ngModel',
            link: function (scope, elm, attrs, ctrl) {

                var argsObject = scope.$eval(attrs.invalidIf);

                if (!angular.isObject(argsObject)) {
                    argsObject = { invalidIf: attrs.invalidIf };
                }

                for (var validationKey in argsObject) {
                    scope.$watch(argsObject[validationKey], function (newVal) {
                        ctrl.$setValidity(validationKey, !newVal);
                    });
                }
            }
        };
    }]);

다음과 같이 사용할 수 있습니다.

<input ng-model="foo" invalid-if="{fooIsGreaterThanBar: 'foo > bar',
                                   fooEqualsSomeFuncResult: 'foo == someFuncResult()'}/>

또는 표현식을 전달하여 ( "invalidIf"의 기본 validationKey가 제공됨)

<input ng-model="foo" invalid-if="foo > bar"/>

13

다음은 양식에서 사용자 정의 와일드 카드 표현식 유효성 검증을 수행하는 멋진 방법입니다 (보낸 사람 : AngularJS 및 필터를 사용한 고급 양식 유효성 검증 ).

<form novalidate="">  
   <input type="text" id="name" name="name" ng-model="newPerson.name"
      ensure-expression="(persons | filter:{name: newPerson.name}:true).length !== 1">
   <!-- or in your case:-->
   <input type="text" id="fruitName" name="fruitName" ng-model="data.fruitName"
      ensure-expression="(blacklist | filter:{fruitName: data.fruitName}:true).length !== 1">
</form>
app.directive('ensureExpression', ['$http', '$parse', function($http, $parse) {
    return {
        require: 'ngModel',
        link: function(scope, ele, attrs, ngModelController) {
            scope.$watch(attrs.ngModel, function(value) {
                var booleanResult = $parse(attrs.ensureExpression)(scope);
                ngModelController.$setValidity('expression', booleanResult);
            });
        }
    };
}]);

jsFiddle 데모 (표현 이름 지정 및 다중 표현식 지원)

와 비슷 ui-validate하지만 범위 특정 유효성 검사 기능 (일반적으로 작동) 이 필요하지 않으며 물론 이 방법으로 ui.utils 가 필요하지 않습니다 .


감사. 매우 시원합니다. 동적 양식에 대한 유효성 검사 규칙을 적용하는 것이 특히 유용합니다. 그러나 여전히 유효하지 않은 모델 값을 설정합니다. 어쨌든 modelValue가 유효하지 않으면 설정하지 못하게합니까?
YuMei

5

최신 정보:

동일한 기능을 가진 이전 지시문의 개선 및 단순화 된 버전 (2 개 대신 1 개) :

.directive('myTestExpression', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            var expr = attrs.myTestExpression;
            var watches = attrs.myTestExpressionWatch;

            ctrl.$validators.mytestexpression = function (modelValue, viewValue) {
                return expr == undefined || (angular.isString(expr) && expr.length < 1) || $parse(expr)(scope, { $model: modelValue, $view: viewValue }) === true;
            };

            if (angular.isString(watches)) {
                angular.forEach(watches.split(",").filter(function (n) { return !!n; }), function (n) {
                    scope.$watch(n, function () {
                        ctrl.$validate();
                    });
                });
            }
        }
    };
}])

사용법 예 :

<input ng-model="price1" 
       my-test-expression="$model > 0" 
       my-test-expression-watch="price2,someOtherWatchedPrice" />
<input ng-model="price2" 
       my-test-expression="$model > 10" 
       my-test-expression-watch="price1" 
       required />

결과 : 다른 지시어 모델과 현재 모델의 변경시 유효성 검사기가 실행되는 상호 의존적 테스트 식입니다.

테스트 표현식에는 지역 $model변수가 있으며 다른 변수와 비교하는 데 사용해야합니다.

이전 :

추가 지시문을 추가하여 @Plantface 코드를 개선하려고 시도했습니다. 이 추가 지시문은 둘 이상의 ngModel 변수에서 변경이 수행 될 때 표현식을 실행해야하는 경우 매우 유용합니다.

.directive('ensureExpression', ['$parse', function($parse) {
    return {
        restrict: 'A',
        require: 'ngModel',
        controller: function () { },
        scope: true,
        link: function (scope, element, attrs, ngModelCtrl) {
            scope.validate = function () {
                var booleanResult = $parse(attrs.ensureExpression)(scope);
                ngModelCtrl.$setValidity('expression', booleanResult);
            };

            scope.$watch(attrs.ngModel, function(value) {
                scope.validate();
            });
        }
    };
}])

.directive('ensureWatch', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        require: 'ensureExpression',
        link: function (scope, element, attrs, ctrl) {
            angular.forEach(attrs.ensureWatch.split(",").filter(function (n) { return !!n; }), function (n) {
                scope.$watch(n, function () {
                    scope.validate();
                });
            });
        }
    };
}])

교차 검증 필드를 만드는 데 사용하는 방법의 예 :

<input name="price1"
       ng-model="price1" 
       ensure-expression="price1 > price2" 
       ensure-watch="price2" />
<input name="price2" 
       ng-model="price2" 
       ensure-expression="price2 > price3" 
       ensure-watch="price3" />
<input name="price3" 
       ng-model="price3" 
       ensure-expression="price3 > price1 && price3 > price2" 
       ensure-watch="price1,price2" />

ensure-expression경우 검증 모델 실행 ng-model또는 임의의 ensure-watch변수를 변화시킨다.


4

@ synergetic @blesh는 함수를 아래와 같이 유효성 검증한다고 가정합니다.

function validate(value) {
    var valid = blacklist.indexOf(value) === -1;
    ngModel.$setValidity('blacklist', valid);
    return valid ? value : undefined;
}

ngModel.$formatters.unshift(validate);
ngModel.$parsers.unshift(validate);

4

서버를 호출하는 사용자 지정 유효성 검사

백엔드에 대한 요청 작성과 같은 비동기 유효성 검증을 처리 하는 ngModelController $asyncValidatorsAPI 를 사용하십시오 $http. 오브젝트에 추가 된 함수는 유효 할 때 해결되거나 유효하지 않은 경우 거부되어야하는 약속을 리턴해야합니다. 진행중인 비동기 유효성 검사는에 키로 저장됩니다 ngModelController.$pending. 자세한 정보는 AngularJS 개발자 안내서-양식 (사용자 정의 유효성 검증)을 참조하십시오 .

ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
  var value = modelValue || viewValue;

  // Lookup user by username
  return $http.get('/api/users/' + value).
     then(function resolved() {
       //username exists, this means validation fails
       return $q.reject('exists');
     }, function rejected() {
       //username does not exist, therefore this validation passes
       return true;
     });
};

자세한 내용은


$validatorsAPI 사용

허용 된 답변은 $parsers$formatters파이프 라인을 사용하여 사용자 지정 동기 유효성 검사기를 추가합니다. 1.3 이상은 추가 AngularJS와 $validators에서 검증 넣을 필요가 없습니다 있도록 API를 $parsers하고 $formatters파이프 라인 :

app.directive('blacklist', function (){ 
   return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {           
          ngModel.$validators.blacklist = function(modelValue, viewValue) {
              var blacklist = attr.blacklist.split(',');
              var value = modelValue || viewValue;
              var valid = blacklist.indexOf(value) === -1;
              return valid;
          });    
      }
   };
});

자세한 정보는 AngularJS ngModelController API 참조-$ validators를 참조 하십시오 .


3

AngularJS에서 사용자 정의 유효성 검사를 정의하는 가장 좋은 장소는 Cutsom 지시어입니다. AngularJS는 ngMessages 모듈을 제공합니다.

ngMessages는 수신하는 키 / 값 객체의 상태에 따라 메시지를 표시하고 숨기도록 설계된 지시문입니다. 지시문 자체는 ngModel $ error 객체 (유효성 검증 오류의 키 / 값 상태를 저장)로 오류 메시지보고를 보완합니다.

사용자 지정 양식 유효성 검사 사용자 지정 지시문과 함께 ngMessages 모듈을 사용해야합니다. 여기서 숫자 길이가 작은 지 확인하고 화면에 오류를 표시하는 간단한 유효성 검사가 있습니다.

 <form name="myform" novalidate>
                <table>
                    <tr>
                        <td><input name='test' type='text' required  ng-model='test' custom-validation></td>
                        <td ng-messages="myform.test.$error"><span ng-message="invalidshrt">Too Short</span></td>
                    </tr>
                </table>
            </form>

맞춤 유효성 검사 지시문을 만드는 방법은 다음과 같습니다.

angular.module('myApp',['ngMessages']);
        angular.module('myApp',['ngMessages']).directive('customValidation',function(){
            return{
            restrict:'A',
            require: 'ngModel',
            link:function (scope, element, attr, ctrl) {// 4th argument contain model information 

            function validationError(value) // you can use any function and parameter name 
                {
                 if (value.length > 6) // if model length is greater then 6 it is valide state
                 {
                 ctrl.$setValidity('invalidshrt',true);
                 }
                 else
                 {
                 ctrl.$setValidity('invalidshrt',false) //if less then 6 is invalide
                 }

                 return value; //return to display  error 
                }
                ctrl.$parsers.push(validationError); //parsers change how view values will be saved in the model
            }
            };
        });

$setValidity 모델 상태를 유효 / 무효로 설정하는 내장 함수


1

유효성 검사가 대소 문자를 구분하는지 여부를 지정하는 기능으로 @ Ben Lesh의 답변을 확장했습니다 (기본값).

사용하다:

<input type="text" name="fruitName" ng-model="data.fruitName" blacklist="Coconuts,Bananas,Pears" caseSensitive="true" required/>

암호:

angular.module('crm.directives', []).
directive('blacklist', [
    function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            scope: {
                'blacklist': '=',
            },
            link: function ($scope, $elem, $attrs, modelCtrl) {

                var check = function (value) {
                    if (!$attrs.casesensitive) {
                        value = (value && value.toUpperCase) ? value.toUpperCase() : value;

                        $scope.blacklist = _.map($scope.blacklist, function (item) {
                            return (item.toUpperCase) ? item.toUpperCase() : item
                        })
                    }

                    return !_.isArray($scope.blacklist) || $scope.blacklist.indexOf(value) === -1;
                }

                //For DOM -> model validation
                modelCtrl.$parsers.unshift(function (value) {
                    var valid = check(value);
                    modelCtrl.$setValidity('blacklist', valid);

                    return value;
                });
                //For model -> DOM validation
                modelCtrl.$formatters.unshift(function (value) {
                    modelCtrl.$setValidity('blacklist', check(value));
                    return value;
                });
            }
        };
    }
]);

0

이 글에서 제시된 몇 가지 훌륭한 예제와 라이브러리가 있지만 내가 찾고있는 것을 가지고 있지 않았습니다. 내 접근 방식 : 각도 유효성 -선택적 부트 스트랩 스타일이 적용된 비동기 유효성 검사를위한 약속 기반 유효성 검사 라이브러리.

OP의 사용 사례에 대한 각도 유효성 솔루션은 다음과 같습니다.

<input  type="text" name="field4" ng-model="field4"
        validity="eval"
        validity-eval="!(field1 && field2 && field3 && !field4)"
        validity-message-eval="This field is required">

여기의 바이올린은 당신이 스핀을 위해 그것을 가지고 싶다면. lib는 GitHub 에서 사용할 수 있으며 자세한 설명서와 많은 라이브 데모가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.