patternDirective = function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, elm, attr, ctrl) {
      if (!ctrl) return;

      var regexp, patternExp = attr.ngPattern || attr.pattern;
      attr.$observe('pattern', function(regex) {
        if (isString(regex) && regex.length > 0) {
          regex = new RegExp('^' + regex + '$');
        }

        if (regex && !regex.test) {
          throw minErr('ngPattern')('noregexp',
            'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp,
            regex, startingTag(elm));
        }

        regexp = regex || undefined;
        ctrl.$validate();
      });

      ctrl.$validators.pattern = function(modelValue, viewValue) {
        // HTML5 pattern constraint validates the input value, so we validate the viewValue
        return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue);
      };
    }
  };
}
@ngdoc directive
@name ngPattern

@description

ngPattern adds the pattern {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls.

The validator sets the `pattern` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
does not match a RegExp which is obtained by evaluating the Angular expression given in the
`ngPattern` attribute value:
* If the expression evaluates to a RegExp object, then this is used directly.
* If the expression evaluates to a string, then it will be converted to a RegExp after wrapping it
in `^` and `$` characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`.

<div class="alert alert-info">
**Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to
start at the index of the last search's match, thus not taking the whole input value into
account.
</div>

<div class="alert alert-info">
**Note:** This directive is also added when the plain `pattern` attribute is used, with two
differences:
<ol>
  <li>
    `ngPattern` does not set the `pattern` attribute and therefore HTML5 constraint validation is
    not available.
  </li>
  <li>
    The `ngPattern` attribute must be an expression, while the `pattern` value must be
    interpolated.
  </li>
</ol>
</div>

@example
<example name="ngPatternDirective" module="ngPatternExample">
  <file name="index.html">
    <script>
      angular.module('ngPatternExample', [])
        .controller('ExampleController', ['$scope', function($scope) {
          $scope.regex = '\\d+';
        }]);
    </script>
    <div ng-controller="ExampleController">
      <form name="form">
        <label for="regex">Set a pattern (regex string): </label>
        <input type="text" ng-model="regex" id="regex" />
        <br>
        <label for="input">This input is restricted by the current pattern: </label>
        <input type="text" ng-model="model" id="input" name="input" ng-pattern="regex" /><br>
        <hr>
        input valid? = <code>{{form.input.$valid}}</code><br>
        model = <code>{{model}}</code>
      </form>
    </div>
  </file>
  <file name="protractor.js" type="protractor">
       var model = element(by.binding('model'));
       var input = element(by.id('input'));

       it('should validate the input with the default pattern', function() {
         input.sendKeys('aaa');
         expect(model.getText()).not.toContain('aaa');

         input.clear().then(function() {
           input.sendKeys('123');
           expect(model.getText()).toContain('123');
         });
       });
  </file>
</example>