Change Angular directive element attribute dynamically

24,814

You can do this in the linking function by

  • Setting the directive's priority high, so it runs before all others.
  • Set it to terminal, so others don't run after it.
  • Recompile the element after you make changes to it (such as adding attributes)

For example:

app.directive('hide', function($compile) {
  return {
    restrict: 'A',
    priority: 10000,
    terminal: true,
    link: function(scope, element, attrs) {
      attrs.$set('ngHide', true);
      attrs.$set('hide', null);
      $compile(element)(scope);
   }
  };
});

As can be seen on http://plnkr.co/edit/tHNvCxVn2wURO38UtI0n?p=preview

Share:
24,814
Alan
Author by

Alan

Updated on October 23, 2020

Comments

  • Alan
    Alan over 3 years

    I am trying to create a custom directive which extends the functionality of an existing element. I would like to detect if a certain attribute exists and if not then add it (e.g. ng-class).

    I have tried to achieve this during pre-compilation but angular does not react to the addition of the new attribute.

    I created a plunker with a simple example using ng-hide.

    <input hide type="submit" value="Submit"/>

    
        app.directive('hide', function() {
          return {
            restrict: 'A',
            compile: function(){
                 return {
                     pre: function(scope, element, attributes, controller, transcludeFn){
                       attributes.$set("ng-hide", true);
                     },
                     post: function(scope, element, attributes, controller, transcludeFn){
    
                     }
                 }
             },
          };
        });
    
    

    If I add ng-hide="true" in the html then the submit button is hidden correctly. If I leave it to the directive then I can see that the DOM has the element set up correctly but the element is not hidden:

    <input hide="" type="submit" value="Submit" ng-hide="true">

    Any help appreciated!

  • Alan
    Alan over 9 years
    You are a genius, thanks! I didn't need to set terminal in the end; priority and compiling the element (with the directive null) did the trick
  • Michal Charemza
    Michal Charemza over 9 years
    I would keep the terminal: true. It might not be technically necessary in the current case, but it does prevent needless recompiling of any other directives on the element.