LoginSignup
5
8

More than 5 years have passed since last update.

AngularJS(1.3)でカスタムバリデーション

Last updated at Posted at 2015-05-30

お遊びを離れ、何かやろうとすると直ぐにカスタムバリデートが必要になるので、そのやり方。

1.3から簡単になったらしいが、その前を知らないので、感動は薄い。

普通?のバリデーションに加え、サーバを非同期で見に行くバリデーションも作れる。ユーザーの一意性チェックなどには重宝するだろう。

やること

  • nameには、普通?のバリデーションんを書けている(全部小文字じゃないとだめ)
  • nicknameはサーバに問合せ、ユニークかどうかをチェックする(サーバはokかngを返すイメージ)

ポイントと課題

非同期のバリデーションはngModel.$asyncValidatorsを使うことで実現できる。また、全部入力時に初めて評価したいため、ng-model-options="{updateOn: 'blur'}"により、フォーカスが外れた時にチェックがかかるようにしている(が、そうならない)。

ng-model-options="{updateOn: 'blur'}"をつけていても、初回読み込み時に1度実行されてしまう。何かやり方がおかしいのだろうけど、初回時は値がundefinedなので、それで判断して場合分けしている・・・。うーん。

あと、ngModel.$asyncValidatorsの返り値はpromise(then...)じゃないとだめ。最初、直接true,falseを返していてしばらくハマった。

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('myCtrl',function($scope){

    //function
    $scope.addUser = function(){
        alert("added");
    }

});

//普通?のバリデーション
app.directive('usernameValidator',function(){
    return{
        restrict: "A",
        require: "ngModel",
        link: function(scope,element,attrs,ngModel){
            ngModel.$validators.username = function(modelValue,viewValue){
                var value = modelValue || viewValue;
                return /^[a-z]+$/.test(value);
            }
        }
    }
});

//サーバを見に行くバリデーション
app.directive('nicknameValidator',function($http,$q){
    return{
        restrict: "A",
        require: "ngModel",
        link: function(scope,element,attrs,ngModel){
            //戻り値はpromiseでなくてはならない(直true, false)ではNGになる。
            ngModel.$asyncValidators.nickname = function(modelValue,viewValue){

                var value = modelValue || viewValue;

                //読み込時は何もしない(''とすると何もしないのでそうしている。なにかよい方法がないか・・・)
                if(value == undefined){
                    return $http.get('').then(function(){

                    },function(){

                    });
                }

                //on blurで非同期チェック
                return $http.get('res.php').then(function(res){
                    if(res.data == "ok"){
                        return true;
                    }else{
                        return $q.reject();
                    }
                });
            }
        }
    }
});
</script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<form novalidate name="myForm" ng-submit="addUser()">

<!-- text -->
<p>
Name:<input type="text" name="name" ng-model="name" username-validator>
<span ng-show="myForm.name.$error.username">name contain only lowercharactors.</span>
</p>

<p>
NickName:<input type="text" name="nickname" ng-model="nickname" nickname-validator ng-model-options="{updateOn: 'blur'}">
<span ng-show="myForm.nickname.$error.nickname">aleady exits.</span>
</p>

<!-- submit -->
<p><input type="submit" value="add"></p>

<pre>{{name}}</pre>
</form>
</body>
</html>

5
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8