Search code examples
javascriptangularjsangularjs-directiveangular-compiler-cli

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/


Solution

  • 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);