Оформление директивы ng-click в AngularJs

Я искал модификацию директивы AngularJS ng-click, чтобы добавить некоторые дополнительные функции. У меня есть несколько разных идей о том, для чего его использовать, но простой - добавить отслеживание Google Analytics ко всем ng-кликам, а другой - предотвратить двойной щелчок.

Для этого моя первая мысль заключалась в использовании декоратора. Так что-то вроде этого:

app.config(['$provide', function($provide) {
  $provide.decorator('ngClickDirective', ['$delegate', function($delegate) {
    // Trigger Google Analytics tracking here
    return $delegate;
  }]);
}]);

Но это не сработает, так как декораторы запускаются при создании экземпляра, а не когда выполняется выражение в директиве. Таким образом, в этом случае он будет аналитиком, когда элемент с директивой загружается, а не при нажатии элемента.

Итак, к реальному вопросу. Есть ли какой-нибудь способ для декоратора получить элемент, который создается в директиве? Если бы я мог, от делегата, добраться до элемента, я мог бы связать свое собственное событие click на нем, чтобы вызвать в дополнение к ng-click.

Если нет, как бы вы добавили что-то во все ng-клики?

Ответ 1

Вы можете использовать декоратор для добавления функциональности. Я сделал быстрый plunkr, чтобы продемонстрировать, как это сделать. В базовом режиме, в вашем корпусе декоратора, вы заменяете функцию компиляции своей собственной для своей пользовательской логики (в примере привязка к событию клика, если присутствует атрибут track), а затем вызывается исходная функция компиляции. Вот фрагмент:

$provide.decorator('ngClickDirective', function($delegate) {
  var original = $delegate[0].compile;
  $delegate[0].compile = function(element, attrs, transclude) {
    if(attrs.track !== undefined) {
      element.bind('click', function() {
        console.log('Tracking this');
      });
    }
    return original(element, attrs, transclude);
  };
  return $delegate;
})

Ответ 2

Это правильная обновленная версия (улучшенная от ответа):

$provide.decorator('ngClickDirective', function($delegate) {
    var compile = $delegate[0].compile;
    $delegate[0].compile = function() {
       var link = compile.apply(this, arguments);
       return function(scope, element, attrs, transclude) {
           if (attrs.track !== undefined) {
               element.bind('click', function() {
                   console.log('Tracking this');
               });
           }
           return link.apply(this, arguments);
       };
    };
    return $delegate;
});