var app = angular.module('plunker', []);


app.directive('uniqueUsername', function($http, errorMessages) {
      return {
        restrict: 'A',
        require: ['ngModel', '^form'],
        link: function (scope, element, attrs, ctrls) {
          
          var ngModel = ctrls[0]
          var formCtrl = ctrls[1]
          var formName = formCtrl.$name
          //console.log(formCtrl)
          
            function validate(value) {
              if (scope.usernames && scope.usernames.indexOf(ngModel.$viewValue) === -1) {
                ngModel.$setValidity('unique', true);
                errorMessages.unset(formName,'unique');
              } else {
                ngModel.$setValidity('unique', false);
                errorMessages.set(formName,'unique', 'Username "' + value + '" is invalid')
              }
            }

            $http.get( "usernames.json").success( function (usernames) {
              scope.usernames = usernames;
              validate(ngModel.$viewValue);
            });
            
            scope.$watch( function() {
              return ngModel.$viewValue;
            }, validate);
            

        }
      };
})
.factory('errorMessages', function () {
  var messages = {}
  
  return {
    register : function (formName) {
      if(angular.isUndefined(messages[formName])) {
        messages[formName] = {}
      }
    },
    set : function (formName, token, message) {
      if(angular.isUndefined(messages[formName])) {
        messages[formName] = {}
      }
      messages[formName][token] = message
    },
    get : function (formName, token) {
      if (angular.isUndefined(token)) {
        return messages[formName] || false;
      } else {
        return messages[formName] && messages[formName][token] || false;
      }
    },
    unset : function (formName, token) {
      angular.isDefined(messages[formName]) && delete(messages[formName][token]);
    }
  }
})
.directive('errorMessages', function (errorMessages) {
  return {
    require : '^?form',
    link : function ($scope, $element, $attrs, formCtrl) {
      var formName;
      
      //If we're inside a form, assume that's our formName, otherwise use the attribute value
      if (formCtrl) {
        formName = formCtrl.$name
      } else {
        formName = $attrs.form
      }
      
      //Validate our errorMessages[formName] exists before binding, otherwise we just get undefined
      if (!errorMessages.get(formName)) {
        errorMessages.register(formName)
      }
      $scope.messages = errorMessages.get(formName)
    }
  }
})
<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script data-require="angular.js@1.2.0-rc1" data-semver="1.2.0-rc1" src="http://code.angularjs.org/1.2.0rc1/angular.js"></script>
    <link data-require="bootstrap-css@2.3.2" data-semver="2.3.2" rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" />
    <script src="app.js"></script>
  </head>

  <body>
    <h2>Custom Validation Example</h2>
    <form name="form" class="form-horizontal" novalidate>
        <div class="control-group">
          <label class="control-label required">Username:</label>
          <div class="controls input-icon">
            <input type="text" name="name" ng-model="name" unique-username="" required />
            <span class="help-inline" ng-show="form.$error.unique">Username taken!</span>
          </div>
        </div>
        <div error-messages>
          <ul ng-show="messages">
            <li ng-repeat="(token, mess) in messages"><strong>{{token}}:</strong>{{mess}}</li>
          </ul>
        </div>
    </form>
    
    <div>
      <p>Note that I am no longer bound by scope, so long as I specify which form to use</p>
      <div error-messages form="form">
          <ul ng-show="messages">
            <li ng-repeat="(token, mess) in messages"><strong>{{token}}:</strong>{{mess}}</li>
          </ul>
        </div>
    </div>
  </body>
</html>
/* Put your css in here */

[
  "chuck", "norris", "foo", "bar", "sammla", "acekia"
]