Reputation: 494
I have a simple angular application thats use directives and dynamically append content to directive using link method. I have to compile that new contents, but if i do so it seems that controller called twice.
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);
}
}
};});
Is there a way to avoid this?
I tried to do like described in this post, but that is not work for me.
Here is a plunker.
Upvotes: 2
Views: 2190
Reputation: 1277
I edited your previous code, sincerely think there is an even better way.
What was happening is that previously you were adding multiple event listeners at the same html element.
Now, i'm destroying everything before compiling again.
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('!');
}
}
};
});
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('!');
}
}
};
});
/* 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;
}
<!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>
Upvotes: 6