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

      var maxlength = -1;
      attr.$observe('maxlength', function(value) {
        var intVal = toInt(value);
        maxlength = isNumberNaN(intVal) ? -1 : intVal;
        ctrl.$validate();
      });
      ctrl.$validators.maxlength = function(modelValue, viewValue) {
        return (maxlength < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlength);
      };
    }
  };
}
@ngdoc directive
@name ngMaxlength
@restrict A

@param {expression} ngMaxlength AngularJS expression that must evaluate to a `Number` or `String`
                                parsable into a `Number`. Used as value for the `maxlength`
                                {@link ngModel.NgModelController#$validators validator}.

@description

ngMaxlength adds the maxlength {@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 `maxlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`}
is longer than the integer obtained by evaluating the Angular expression given in the
`ngMaxlength` attribute value.

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

@example
<example name="ngMaxlengthDirective" module="ngMaxlengthExample">
  <file name="index.html">
    <script>
      angular.module('ngMaxlengthExample', [])
        .controller('ExampleController', ['$scope', function($scope) {
          $scope.maxlength = 5;
        }]);
    </script>
    <div ng-controller="ExampleController">
      <form name="form">
        <label for="maxlength">Set a maxlength: </label>
        <input type="number" ng-model="maxlength" id="maxlength" />
        <br>
        <label for="input">This input is restricted by the current maxlength: </label>
        <input type="text" ng-model="model" id="input" name="input" ng-maxlength="maxlength" /><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 maxlength', function() {
         input.sendKeys('abcdef');
         expect(model.getText()).not.toContain('abcdef');

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