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

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

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

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

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



답변

편집 : 아래에 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


답변

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


답변

유효성 검증 시나리오에 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>


답변

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의 저자입니다


답변

최근에 각도 형식 입력의 표현식 기반 무효화를 허용하는 지시문을 작성했습니다. 유효한 각도 식을 사용할 수 있으며 객체 표기법을 사용하여 사용자 지정 유효성 검사 키를 지원합니다. 각도 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"/>


답변

다음은 양식에서 사용자 정의 와일드 카드 표현식 유효성 검증을 수행하는 멋진 방법입니다 (보낸 사람 : 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 가 필요하지 않습니다 .


답변

최신 정보:

동일한 기능을 가진 이전 지시문의 개선 및 단순화 된 버전 (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변수를 변화시킨다.