Joseph Webber Joseph Webber - 2 months ago 15
AngularJS Question

How can I pass ng-click to the element my directive replaces?

Using the angular directive Max created on this post for easily importing SVGs, I've imported a handful of SVGs on my page. I now want to add a click event to an SVG, except the directive doesn't transfer the click method to the imported SVG. If I inspect the SVG in my browser I see that it is indeed missing the ng-click.

HTML

<svg-image class="svg foo" src="img/foo.svg" ng-click="bar()"></svg-image>


JS

$scope.bar = function() {
console.log("click");
};


If I move
ng-click="bar()"
to another element on my page it works just fine. I've also tried moving
ng-click="bar()"
to the svg file itself which didn't work, and I've tried doing what was suggested in this post which didn't work either.

plunker as requested: https://plnkr.co/edit/eqOZJO5Ar8oOmXCjg3Vs

Answer

One of possible solutions is to compile your new element and call resulting template function, passing in scope:

.directive('svgImage', ['$http', '$compile', function($http, $compile) {
  return {
    restrict: 'E',
    link: function(scope, element, attrs) {
      var imgURL = element.attr('src');
      // if you want to use ng-include, then
      // instead of the above line write the bellow:
      // var imgURL = element.attr('ng-include');
      var request = $http.get(
        imgURL,
        {'Content-Type': 'application/xml'}
      );

      scope.manipulateImgNode = function(data, elem){
        var $svg = angular.element(data)[4];
        var imgClass = elem.attr('class');
        if(typeof(imgClass) !== 'undefined') {
          var classes = imgClass.split(' ');
          for(var i = 0; i < classes.length; ++i){
            $svg.classList.add(classes[i]);
          }
        }
        $svg.removeAttribute('xmlns:a');
        angular.element($svg).attr("ng-click", attrs.ngClick);
        return $compile($svg)(scope);
      };

      request.success(function(data){
        element.replaceWith(scope.manipulateImgNode(data, element));
      });
    }
  };
}]);

Plunker