밸리데이트 디렉티브

ngForm 클래스명 활용하기에서 앵귤러 폼에서 자동으로 붙여주는 클래스에 대해 확인해봤다. 그중 .ng-invalid, .ng-valid클래스가 붙는데 다음과 같은 경우에 발생한다.

인풋 필드의 타입이 type="number"일 경우. 실제 입력값이 숫자이면 .ng-valid가 붙고 그렇지 않고 문자열이면 .ng-invalid 클래스가 붙는다. 인풋 필드의 종류 뿐만이아니라 필드 값의 길이와 패턴 그리고 입력 여부에 따라서도 이러한 클래스가 자동으로 설정되도록 할수 있다. 아래 디렉티브는 인풋 필드에 설정하여 이러한 기능을 하도록하는 디렉티브들이다.

  • ng-required: 필드 값이 반드시 있어야한다.
  • ng-minlength: 필드 값의 최소 길이를 설정한다.
  • ng-maxlength: 필드 값의 최대 길이를 설정한다.
  • ng-pattern: 필드 값이 설정한 정규 표현식을 만족해야한다.

폼 객체

전화번호 입력을 위한 필드를 만들어보자.

<form name="form" ng-submit="submit()" novalidate>
  <label for="phone">Phone Number:</label>
  <input type="text" name="phone" ng-model="phone" ng-required="true" ng-minlength="12" ng-maxlength="13" ng-pattern="/^\d{3}-\d{3,4}-\d{4}$/"/>
</form>

‘form’ 이라는 이름을 같은 폼 엘레먼트 안에 ‘phone’이라는 텍스트 입력 필드를 만들었다. 이 필드의 제약사항은 1) 반드시 필드 값이 입력되어야 하고(ng-required="true") 2) 입력된 값의 최소길이는 12글자(ng-minlength="12") 3) 최대 길이는 13글자 (ng-maxlength="13") 4) 그리고 전화번호 형식의 정규 표현식을 만족해야 한다. (ng-pattern="/^\d{3}-\d{3,4}-\d{4}$/")

이렇게 설정한 밸리데이터는 스코프 변수를 통해 접급할 수 있다. 아무것도 입력하지 않은 상태에서 $scope.form.name 객체를 살펴보자.

"phone": {
    "$validators": {},
    "$asyncValidators": {},
    "$parsers": [],
    "$formatters": [
      null
    ],
    "$viewChangeListeners": [],
    "$untouched": true,
    "$touched": false,
    "$pristine": true,
    "$dirty": false,
    "$valid": false, // 필드값이 검증되면 true로 설정됨
    "$invalid": true, // 필드값 검증에 실패하면 true로 설정됨
    "$error": { // 밸리데이터로 검증한 결과 정보를 담는 객체
      "required": true
    },
    "$name": "phone",
    "$options": null
  }

이번엔 “010-1234-“를 필드에 입력해 보자.

"phone": {
    "$viewValue": "010-1234-", // 필드에 입력한 값을 저장한다.
    "$validators": {},
    "$asyncValidators": {},
    "$parsers": [],
    "$formatters": [
      null
    ],
    "$viewChangeListeners": [],
    "$untouched": false,
    "$touched": true,
    "$pristine": false,
    "$dirty": true,
    "$valid": false, // 입력값 검증을 실패했다.
    "$invalid": true, // 입력값 검증을 실패했다.
    "$error": {
      "pattern": true, // 입력값이 정규표현식 검증에 실패했다.
      "minlength": true // 입력한 값이 최소 13글자가 아니다.
    },
    "$name": "phone",
    "$options": null
  }

필드에 입력한 값은 $viewValue에 저장된다. 이 값이 검증에 통과하지 못하면 $valid=false, $invalid=true로 설정된다. 그리고 $error 객체에 어떤 검증에 실패하였는지 정보를 담아준다.

그럼 제대로 된 값을 입력해보자. 010-1234-5678을 입력한 결과다.

"phone": {
    "$viewValue": "010-1234-5678",
    "$modelValue": "010-1234-5678", // 검증에 성공하면 모델값에 저장한다.
    "$validators": {},
    "$asyncValidators": {},
    "$parsers": [],
    "$formatters": [
      null
    ],
    "$viewChangeListeners": [],
    "$untouched": false,
    "$touched": true,
    "$pristine": false,
    "$dirty": true,
    "$valid": true, // 검증에 성공했다.
    "$invalid": false, // 검증에 성공했다.
    "$error": {}, // 에러가 없다.
    "$name": "phone",
    "$options": null
  }

입력값 검증에 성공하면 $viewValue에 저장된 값이 $modelValue에도 저장된다. 이것은 필드에서 ng-model="phone"로 설정한 모델값에도 반영되어 $scope.phone으로도 접근할 수 있다. $valid=true, $invalid=false가 설정되고 $error 객체는 비워진다.

안내 문구

폼 객체를 살펴보았으니 이것을 활요해 안내 문구를 출력해보자. 사용자가 필드값을 입력하면 폼 객체체의 $error 필드를 확인하여 상황에 맞는 메세지를 보여줄 수 있다.

<p ng-show="form.phone.$error.required">전화번호를 입력하세요</p>
<p ng-show="form.phone.$error.minlength">최소 13글자 이상 입력하세요</p>
<p ng-show="form.phone.$error.maxlength">최대 14글자까지 입력하세요</p>
<p ng-show="form.phone.$error.pattern">010-xxx-xxxx 형식으로 입력하세요</p>

폼 객체의 $submitted를 활용하면 폼을 제출했을 경우에만 메세지를 출력할수도 있다.

<p ng-show="form.phone.$error.required && form.$submitted">전화번호를 입력하세요</p>
<p ng-show="form.phone.$error.minlength && form.$submitted">최소 13글자 이상 입력하세요</p>
<p ng-show="form.phone.$error.maxlength && form.$submitted">최대 14글자까지 입력하세요</p>
<p ng-show="form.phone.$error.pattern && form.$submitted">010-xxx-xxxx 형식으로 입력하세요</p>

<button type="submit"> 제출

소스코드