AngularJS1で、独自に定義したディレクティブで作成するテンプレート内のなんかの要素をクリックされた時にその要素を使ってなんかしたいといった時に、試行錯誤してやっとできたのでメモ。そもそもディレクティブやスコープをよく理解してないのでアレだけど…

クリックした時の処理をng-clickで指定する場合

例えば独自のディレクティブfooで、クリックされた時の処理をng-clickで指定するとして

<foo ng-click="onClick(ev)">Click me 1</foo>

それをハンドルするためには、以下のようになった:

// app.js
angular.module('app', [])
  .controller('FooController', ['$scope', function($scope) {
    $scope.onClick = function($event) {
      console.log($event.currentTarget)
    }
  }])
  .directive('foo', function() {
    return {
      scope: {
        ngClick: '&',
      },
      link: function(_scope, element, _attrs, _ctrl, _transclude) {
        element.removeAttr('ng-click')
        element.off('click')
      },
      restrict: 'AE',
      transclude: true,
      template: ('FOO[' +
                 '<a href="#" ng-click="ngClick({ev: $event})" ng-transclude>' +
                 '</a>' +
                 ']'),
    }
  })
  • directivescopengClick&指定して、親スコープでのものにする(?)
  • templateで、fooタグで展開する内容の中の例えばaタグのng-clickに設定する際に、その中で呼び出すngClickへの引数にはオブジェクトでパラメータ名を指定して渡す({ev: $event}
    • この場合、htmlのfooタグのng-click内で使用する変数evに、aタグがクリックされた時のイベント情報$eventを割り当てることになる(?)
    • ev$eventという名前に変えれば、htmlのng-click内でも通常と同じように$eventがイベント情報として使える、がここでは区別しやすくするため別名とした
  • ng-clickの内容はaタグに移すので、directivelink関数内でelement(実体はfooタグ)からng-clickを削除
  • 削除してもクリックハンドラは設定されてしまっているようなので、element.off('click')でハンドラを解除

以上で、aタグがクリックされた時にスコープのonClickが呼び出されて、そのパラメータ$eventにはng-clickのイベント$eventが渡ってきて、そのcurrentTargetaタグが取得できる

暗黙的に呼び出す関数を指定する場合

ディレクティブで暗黙的に呼び出す関数を指定する場合、例えば

<bar>Click me 2</bar>

などとしたときにクリックされたら自動的にonClick関数を呼び出すとする場合、以下のようにする:

// app.js
...
  .directive('bar', function($compile) {
    return {
      restrict: 'AE',
      transclude: true,
      template: ('BAR[' +
                 '<a href="#" ng-click="onClick($event)" ng-transclude>' +
                 '</a>' +
                 ']'),
    }
  })
  • この場合、展開される場所のスコープがそのまま使えるので、onClick($event)でそのまま呼び出せる

デモ

https://jsfiddle.net/agfs6pft/2/