AngularJS Directive for specific tag name

10,098

Solution 1

You have 2 options.

#1 Use your existing directive that you have working and add a couple lines

code:

link: function(scope,element,attr) {

    if (element[0].tagName== 'IMG') {
        //do your stuff
    } else {
        // do nothing or something else
    }
}

#2 Restrict your directive to be just an element (as shown in Fizer Khan's answer).

.directive('myIMG', function() {
    return {
      restrict: 'E',
      templateUrl: 'img.html',//essentially has <img src=''>
      template: "<img src='scope.path'>",//build out your image tag here which will replace the HTML the directive is on
      transclude: true,
      scope: {
          path: '='
      },
      link: function(scope, element, attr) {

      }
    };
  });

HTML

<myIMG path=''></myIMG>

I personally like option 2 best. But I know that can be more daunting, and often introduces other unexpected things.

Solution 2

Simplest approach

Define directive of specific HTML tag

Even though this question has been asked long ago there's no answer that creates directive on the required element itself. So here's another possible way of defining an Angular directive that restricts itself to IMG tags

appModule
    .directive("img", function() {
        restrict: "E",
        link: function(scope, element, attributes) {
            if (!element.hasClass("something") && !attributes.something)
            {
                // just a normal image
                return;
            }

            // do your stuff
        }
    });

This code defines a directive for IMG element but when it initializes it checks that there's either a specific CSS class and/or HTML attribute defined on it. If it doesn't have any, it gracefully exits as this image should not be directed. But if any of those is defined on it, it does its thing.

Best approach

Two directives on the same element with requirements

The following is likely the best possible Angular approach to this. IT consists of two directives. One that is on the img element and the other that is an attribute/class directive and requires img directive.

appModule
    .directive("img", function() {
        restrict: "E",
        controller: function imgController() {
            // does nothing really
        }
    })
    .directive("imgSpecific", function() {
        restrict: "AC",
        require: "img",
        link: function() {
            // do your stuff
        }
    });

So the second directive actually requires an img directive which is restrictive to image elements on the same element and if present, then this directive will actually run, otherwise it will produce a runtime exception as its requirements aren't met.

By doing it this way, both directives will be very simple without any specific code that checks certain conditions for the directive to actually execute. All this checks are already done within Angular code and our directives (the second/child one specifically) will only execute on image elements when both are present.

Solution 3

You can set restrict attribute to E in the directive

 restrict: 'E'

The tag name always be directive name.

Example

 angular.module('myapp', [])
.directive('myTag', function() {
    return {
      restrict: 'E',
      templateUrl: 'my-tag.html',
      scope: {

      },
      link: function(scope, element, attr) {

      }
    };
  });

Only way to use this directive is

<my-tag></mytag>

Solution 4

Id suggest you support both approaches, as Angular does not restrict to element tag name. It seems to come down to how you want to handle what, in your design, is a user error. The user should only ever use your directive on an img element so what do you want to do when they dont follow your intentions? If you want to handle the error gracefully and continue then insert an img for them and proceeed.

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

<html>

<head>
<script data-require="angular.js@*" data-semver="1.2.16" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>

<body>

<img src="http://www.w3.org/html/logo/img/badge-samples.png" img-test>
<div data-src="http://www.w3.org/html/logo/img/badge-samples.png" img-test></div>
<script>

  var app=angular.module("app",[]);

  app.directive("imgTest",function(){
    var link=function(scope,elem,attrs){
      var img;
      if(elem.tagName !="IMG"){
        img=document.createElement("img");
        img.setAttribute("src",attrs.src);
        elem.append(img);
      }
    };

    return{
      "link" : link
    }
  });

  angular.bootstrap(document,["app"]);

</script>

Share:
10,098
Naor
Author by

Naor

My name is Naor and I live in the holy city Jerusalem of Israel. I am 31 years old, married to my lovely Ilana and we have a female cat named Mutzi. I am working as web developer and I create web apps in my free time.

Updated on July 25, 2022

Comments

  • Naor
    Naor almost 2 years

    How can I force specific tag for a directive in AngularJS?

    For example, I want to create a directive that will be applied only on <img> tags. If the user put this directive on a <div>, I don't want the directive to be active. How can I do that?