<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@1.1.4" data-semver="1.1.4" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.1.4/angular.js"></script>
    <script data-require="underscore.js@1.5.1" data-semver="1.5.1" src="//cdn.jsdelivr.net/underscorejs/1.5.1/underscore-min.js"></script>
    <script data-require="moment.js@*" data-semver="2.5.1" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body data-ng-app="myApp" data-ng-controller="searchCtrl">

    <div class="errors">
      <!-- We use submitted to hide all error msgs until its actually submitted-->
      <ul data-ng-show="searchForm.submitted">
        <li data-ng-show="searchForm.leaving_from.$invalid">Departure Airport is invalid</li>
        <li data-ng-show="searchForm.leaving_from.$error.required">Departure Airport is required</li>
        <li data-ng-show="searchForm.leaving_from.$error.minlength">Departure Airport should be at least 3 charachters</li>
        <li data-ng-show="searchForm.leaving_from.$error.invalidAiportCode">Airport Code should start with letter A</li>
      </ul>
    </div>
    
    <form name="searchForm" novalidate="" role="form">
      <!-- Required: out of the box validation -->
      <label for="leaving_from" data-ng-class="{'error-req': searchForm.submitted &amp;&amp; searchForm.leaving_from.$invalid}">From<span class="ada-hide"> City or airport</span>*</label>
      <input type="text" placeholder="City or airport" id="leaving_from" name="leaving_from" 
        data-ng-model="search.leavingFrom" required data-ng-minlength="3"
        my-validate-airport-code>
      <br />
      
      <button type="submit" data-ng-click="submitSearch()">submit</button>
      <button data-ng-click="reset()">reset</button>
    </form>
  </body>

</html>
// Code goes here

myApp = angular.module("myApp", []);
    
myApp.controller("searchCtrl", function($scope){
  
  // This is to hold the validation until we submit the form.
  $scope.submitSearch = function(){
    if($scope.searchForm.$valid) {
      console.log("form sent");
    }else{
      // If form is invalid, show errors
      $scope.searchForm.submitted = true;
    }
  }
  
  // This is to reset the search model and all errors from screen.
  $scope.reset = function(){
    $scope.search = {}
    $scope.searchForm.submitted = false;
  }

});

myApp.directive("myValidateAirportCode", function(){
  // requires an isloated model
  return {
   // restrict to an attribute type.
   restrict: 'A',
  // element must have ng-model attribute.
   require: 'ngModel', 
   link: function(scope, ele, attrs, ctrl){

      // add a parser that will process each time the value is 
      // parsed into the model when the user updates it.
      ctrl.$parsers.unshift(function(value) {
        if(value){
          // test and set the validity after update.
          var valid = value.charAt(0) == 'A' || value.charAt(0) == 'a';
          ctrl.$setValidity('invalidAiportCode', valid);
        }
          
        // if it's valid, return the value to the model, 
        // otherwise return undefined.
        return valid ? value : undefined;
      });
      
   }
  }
});
/* Styles go here */
.error-req {
  color: red;
}