requiredDirective = function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, elm, attr, ctrl) {
      if (!ctrl) return;
      attr.required = true; // force truthy in case we are on non input element

      ctrl.$validators.required = function(modelValue, viewValue) {
        return !attr.required || !ctrl.$isEmpty(viewValue);
      };

      attr.$observe('required', function() {
        ctrl.$validate();
      });
    }
  };
}
@ngdoc directive
@name ngRequired
@restrict A

@description

ngRequired adds the required {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}.
It is most often used for {@link input `input`} and {@link select `select`} controls, but can also be
applied to custom controls.

The directive sets the `required` attribute on the element if the Angular expression inside
`ngRequired` evaluates to true. A special directive for setting `required` is necessary because we
cannot use interpolation inside `required`. See the {@link guide/interpolation interpolation guide}
for more info.

The validator will set the `required` error key to true if the `required` attribute is set and
calling {@link ngModel.NgModelController#$isEmpty `NgModelController.$isEmpty`} with the
{@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} returns `true`. For example, the
`$isEmpty()` implementation for `input[text]` checks the length of the `$viewValue`. When developing
custom controls, `$isEmpty()` can be overwritten to account for a $viewValue that is not string-based.

@example
<example name="ngRequiredDirective" module="ngRequiredExample">
  <file name="index.html">
    <script>
      angular.module('ngRequiredExample', [])
        .controller('ExampleController', ['$scope', function($scope) {
          $scope.required = true;
        }]);
    </script>
    <div ng-controller="ExampleController">
      <form name="form">
        <label for="required">Toggle required: </label>
        <input type="checkbox" ng-model="required" id="required" />
        <br>
        <label for="input">This input must be filled if `required` is true: </label>
        <input type="text" ng-model="model" id="input" name="input" ng-required="required" /><br>
        <hr>
        required error set? = <code>{{form.input.$error.required}}</code><br>
        model = <code>{{model}}</code>
      </form>
    </div>
  </file>
  <file name="protractor.js" type="protractor">
       var required = element(by.binding('form.input.$error.required'));
       var model = element(by.binding('model'));
       var input = element(by.id('input'));

       it('should set the required error', function() {
         expect(required.getText()).toContain('true');

         input.sendKeys('123');
         expect(required.getText()).not.toContain('true');
         expect(model.getText()).toContain('123');
       });
  </file>
</example>