0

I have created a directive that check if data was entered to an HTML element in the following way:

var myApp = angular.module('myApp', []);

myApp.directive("uiRequired", function () {
return function (scope, elem, attrs) {
    elem.bind("blur", function () {
        var $errorElm = $('#error_testReq');
        $errorElm.empty();
        if (angular.isDefined(attrs) && angular.isDefined(attrs.uiRequired) && attrs.uiRequired == "true" && elem.val() == "") {
            $errorElm.append("<li>Field value is required.</li>");
            $errorElm.toggleClass('nfx-hide', false);
            $errorElm.toggleClass('nfx-block', true);
        }
        else
        {
            $errorElm.toggleClass('nfx-hide', true);
            $errorElm.toggleClass('nfx-block', false);
        }
    });
};

});

A working example can be seen here

My question: Is there a way of adding the directive (uiRequired) I have created dynamically to elements on screen on document ready.

I want to put the new directive on selected HTML elements according to pre-defined list I have. I can not know in advance on which field this directive has to be on.

So I have to put it while page is rendering.

I have tried putting it dynamically myself while page is loading, however AngularJS did interpret it.

I could not find an example on the internet that does that.

Can anyone help me?

1 Answer 1

2

You can dynamically add directives to a page during the compilation phase when Angular is walking the DOM and matching elements to directives. Each step of the compilation process may transform the DOM tree ahead of it, but you should never modify elements that Angular has already compiled. This point is important to remember because adding directives to elements that have already been walked will have no effect. Of course, there ways around this. For example, you could re-compile and re-link previously walked elements. However I strongly advise against this as it may lead to unintended side effects such as memory leaks, and slow performance.

To dynamically add uiRequired directives, you can create a parent directive - let's call it uiRequiredApplier.

app.directive('uiRequiredApplier', function($scope) {
      return {
           restrict: 'A',
           compile: function(element, attr) {
                 // you can apply complex logic figure out which elements
                 // you want to add the uiRequired attribute to
                 $('input', element).attr('uiRequired','');
                 return function(scope, element, attr) {
                 }
           }
      }
});

You can then apply the attribute like this:

<div ui-required-applier>
    <input type="text" ng-model="name" />
</div> 

When the uiRequiredApplier is compiled, it will dynamically add uiRequired attributes to selected elements using jQuery that have not been compiled yet. And when Angular walks the DOM, eventually it will compile and link the uiRequired attributes, which will add the desired validation behavior.

Sign up to request clarification or add additional context in comments.

2 Comments

what if you want to add directives dynamically based on a validation? For ex, I want to add ng-class in an element when it is no longer disabled (which only happens if a previous input has been filled out)... how would I go about into doing that?
It depends on what you are trying to do. do you really need ngClass? Or can you programatically add the classes you need? For dynamic directives involving ngModel validation, I recommend the latter: add classes using DOM manipulation instead of relying on custom directives and the angular compilation process.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.