How to add validation attributes in an angularjs directive

I am trying to write an angular directive that adds validation attributes to the tag, but it doesn’t seem to be working. Here is my demo. You will notice that “Is Valid” remains true if you delete the text in the second input box, but goes to false if you delete the text in the first input box.

http://plnkr.co/edit/Rr81dGOd2Zvio1cLYW8D?p=preview

Here is my directive:

angular.module('demo', [])
.directive('metaValidate', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.attr("required", true);
        }
    };
});

I’m guessing I am just missing something simple.

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

All rules for validation of the form are being read in compilation phase of the form, so after making changes in a child node, you need to recompile form directive (form it’s a custom directive in AngularJS). But do it only once, avoid infinite loops (your directive’s ‘link’ function will be called again after form’s compilation).

angular.module('demo', [])
.directive('metaValidate', function ($compile) {
    return {
        restrict: 'A',
        link: function (scope,element, attrs) {
          if (!element.attr('required')){
            element.attr("required", true);
            $compile(element[0].form)(scope);
          }
        }
    };
});

Working plunker: http://plnkr.co/edit/AB6extu46W4gFIHk0hIl?p=preview

Solution 2

Be careful of infinite loops and recompiles, a better solution is here: Add directives from directive in AngularJS

angular.module('app')
  .directive('commonThings', function ($compile) {
    return {
      restrict: 'A',
      terminal: true, //this setting is important to stop loop
      priority: 1000, //this setting is important to make sure it executes before other directives
      compile: function compile(element, attrs) {
        element.attr('tooltip', '{{dt()}}');
        element.attr('tooltip-placement', 'bottom');
        element.removeAttr("common-things"); //remove the attribute to avoid indefinite loop
        element.removeAttr("data-common-things"); //also remove the same attribute with data- prefix in case users specify data-common-things in the html

        return {
          pre: function preLink(scope, iElement, iAttrs, controller) {  },
          post: function postLink(scope, iElement, iAttrs, controller) {  
            $compile(iElement)(scope);
          }
        };
      }
    };
  });

Working plunker is available at: http://plnkr.co/edit/Q13bUt?p=preview

Solution 3

I know this is quite an old question, but for what it’s worth, the angular docs describe ng-required which takes a boolean value. This solved a similar problem I was having.

http://docs.angularjs.org/api/ng/directive/input

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply