如果在指令上使用$ compile,控制器会触发两次

时间:2015-05-30 11:01:45

标签: angularjs angularjs-directive

我有一个简单的角度应用程序,它使用指令并使用链接方法动态地将内容附加到指令。我必须编译新内容,但如果我这样做,似乎控制器调用了两次。

app.directive('comment', function ($compile) {
return {
    restrict: 'E',
    template: '<div class="commentItem" ng-controller="MainCtrl">' +
                  '<span class="comment">{{comment.message}}</span>' +
                  '<span class="replyToComment" ng-click="doSmth()">doSmth</span>' + 
              '</div>',
    scope: {
        comment: '='
    },
    link: function (scope, element, attrs) {
        if (angular.isArray(scope.comment.comments)) {
            element.append("<comments comments='comment.comments'></comments>");
            $compile(element.contents())(scope);
        }
    }
};});

有没有办法避免这种情况?

我尝试像this帖子中描述的那样做,但这对我不起作用 这是plunker

1 个答案:

答案 0 :(得分:5)

我编辑了您的previous code,真诚地认为还有更好的方式。

以前您在同一个html元素中添加了多个事件侦听器。

现在,我在再次编译之前就摧毁了所有内容。

app.directive('comment', function ($compile) {
    return {
        restrict: 'E',
        template: '<div class="commentItem">' +
                      '<span class="comment">{{comment.message}}</span>' +
                      '<span class="replyToComment" ng-click="doSmth()">doSmth</span>' + 
                  '</div>',
        scope: {
            comment: '='
        },
        link: function (scope, element, attrs) {
            if (angular.isArray(scope.comment.comments)) {
                element.append("<comments comments='comment.comments'></comments>");
                var html = element.html();
                // Removing all contents and old listeners
                element.contents().remove();
                // Creating a new element
                element.html(html);
                // Adding new listeners
                $compile(element.contents())(scope);
            }
            scope.doSmth = function() {
               alert('!');
            }
        }
    };
});

&#13;
&#13;
var app = angular.module('example', []);

app.controller('MainCtrl', function($scope) {
  $scope.comments = [{
    message: 'parent 1',
    comments: [{
      message: 'p1_child1'
    }, {
      message: 'p1_child2',
      comments: [{
        message: 'p1c2_child1'
      }]
    }]
  },{
    message: 'parent 2'
  },{
    message: 'parent 3'
  }];
});
app.directive('comments', function() {
     return {
         restrict: 'E',
         replace: true,
         template: '<div class="commentBlock">'+
                      '<comment ng-repeat="comment in comments" comment="comment"></comment>' +
                  '</div>',
         scope: {
             comments: '='
         }
     };
});
app.directive('comment', function ($compile) {
    return {
        restrict: 'E',
        template: '<div class="commentItem">' +
                      '<span class="comment">{{comment.message}}</span>' +
                      '<span class="replyToComment" ng-click="doSmth()">doSmth</span>' + 
                  '</div>',
        scope: {
            comment: '='
        },
        link: function (scope, element, attrs) {
            if (angular.isArray(scope.comment.comments)) {
                element.append("<comments comments='comment.comments'></comments>");
                var html = element.html();
                element.contents().remove();
                element.html(html);
                $compile(element.contents())(scope);
            }
            scope.doSmth = function() {
               alert('!');
            }
        }
    };
});
&#13;
/* Put your css in here */
.commentItem {
  border: 1px dashed black;
  margin: 20px;
}
.replyToComment {
  display: block;
  float: right;
  color: mediumblue;
}
.comment {
  font-size: larger;
  display: block;
  padding-left: 30px;
}
.commentBlock:not(:first-of-type) {
  padding-left: 20px;
}
.replyToComment:hover {
  cursor: pointer;
}
&#13;
<!DOCTYPE html>
<html ng-app="example">
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="style.css" />
    <script src="https://code.angularjs.org/1.3.15/angular.js"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <comments comments="comments"></comments>
  </body>
</html>
&#13;
&#13;
&#13;