<!DOCTYPE html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular-messages.min.js"></script>
        <script src="script.js"></script>
        
        <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body ng-app="app">
        <div ng-controller="MainCtrl">
            <form name="myForm" ng-submit="submit()">
                <div>
                    <label>
                        Username: <input type="text" ng-model="signup.username" name="username" required username-validator>
                    </label>
                    <div ng-if="myForm.username.$dirty">
                        <div ng-messages="myForm.username.$error" class="validation-error">
                            <div ng-message="required">Username required</div>
                            <div ng-message="username">Username already in use</div>
                        </div>
                        <div ng-messages="myForm.username.$pending" class="validation-pending">
                            <div ng-message="username">Checking username availability...</div>
                        </div>
                    </div>
                </div>
                <div>
                    <label>
                        Password: <input type="password" ng-model="signup.password" name="password" required>
                    </label>
                    <div ng-messages="myForm.password.$error" ng-if="myForm.password.$dirty" class="validation-error">
                        <div ng-message="required">Password required</div>
                    </div>
                </div>
                <button type="submit" ng-disabled="myForm.$invalid || myForm.$pending">Submit</button>
            </form>
        </div>
    </body>
</html>
angular.module('app', ['ngMessages'])
                .controller('MainCtrl', function($scope) {
                    $scope.signup = {};
                    $scope.submit = function() {
                        console.log('submitting', $scope.signup.username, $scope.signup.password);
                    };
                })
                .directive('usernameValidator', function($q, $timeout) {
                    return {
                        require: 'ngModel',
                        link: function(scope, element, attrs, ngModel) {
                            ngModel.$asyncValidators.username = function(modelValue, viewValue) {
                                if (!viewValue) {
                                    return $q.when(true);
                                }
                                var deferred = $q.defer();
                                $timeout(function() {
                                    // Faking actual server-side validity check with $http.
                                    // Let's pretend our service is so popular all short username are already taken
                                    if (viewValue && viewValue.length < 5) {
                                        deferred.reject();
                                    }

                                    deferred.resolve();
                                }, 2000);
                                return deferred.promise;
                            };
                        }
                    };
                });
.validation-error {
  color: red;
}
.validation-pending {
  color: orange;
}