Amit Amit - 2 months ago 28
Javascript Question

angular directive compiler fired ng-click twice

I am using accordion directive in my template, and inside accordion i am adding

attr
ng-click
on a element. When I click on that element it fires twice.

Fiddle : http://jsfiddle.net/Lvc0u55v/10071/

Code :

//accordion directive
.directive('simpleAccordion', function($compile, $timeout) {
return {
restrict: 'AEC',
controller: function($scope) {
$scope.current = null;
$scope.height = [];
$scope.zero = {
height: 0
};
$scope.toggle = function(i) {
$scope.current = $scope.current === i ? null : i;
};
},
link: function(scope, el, attrs) {
var itemSelector = '[item-selector]' || 'li',
titleSelector = '[title-selector]' || 'h2',
contentSelector = '[content-selector]' || 'div';
$timeout(function(){
var items = el[0].querySelectorAll(itemSelector);
for (var i in items) {
if (angular.isObject(items[i])) {
var title = items[i].querySelectorAll(titleSelector)[0];
var content = items[i].querySelectorAll(contentSelector)[0];
scope.height.push({
'height': (content.offsetHeight + 10) + 'px'
});
angular.element(items[i]).addClass('item').attr({
'ng-class': '{\'open\':current == ' + i + '}'
});
angular.element(title).addClass('title').attr('ng-click', 'toggle(' + i + ')');
angular.element(content).addClass('content').attr({
'ng-style': 'current == ' + i + '?height[' + i + ']:zero'
});;

}
}
$compile(angular.element(el).contents())(scope);
});
}
}
})


Fiddle : http://jsfiddle.net/Lvc0u55v/10071/

Answer

By default angular compiles all content of your directive, so then you call compile in link function, ng-click will be compiled twice.

To prevent these behavior, protect your html from compiling by terminal and priority attrs, and compile it manually, excluding your directive by third argument(priority).

change directive definition to:

{
....
terminal: true,
priority: 1000
...
}

and call compile like: $compile(el, null, 1000);

Comments