Event Delegation Directive In use cases where web applications utilize ng-repeat heavily and also rely on event triggers for each item in the collection, such as ng-click and the like, watchers become too numerous and may adversely affect performance when the number of items grow large.

To remedy this problem, an event delegation directive could handle the work. It is unfortunate that AngularJS does not support this as a built-in feature, but perhaps they might include it in a future release. Please review my code example for such a directive and point out any areas for improvement or if there's a better implementation.

Note: This example assumes that the view model (not shown) contains an array of items and a function called doSomething. 

Update: Here is a working example in JSBin to illustrate its use.

Markup

&lt;ul evt-delegate="doSomething(item)" evt-selector="li"&gt;
  &lt;li ng-repeat="item in items"&gt;{{item.name}}&lt;/li&gt;
&lt;/ul&gt;


Code

(function () {
  angular.module('myModule').directive('evtDelegate', ['$parse', delegateDirective]);

  function delegateDirective($parse) {
    return {
      restrict: 'A',
      scope: {
        selector: '='
      },
      link: link
    };

    function link(scope, element, attributes) {
      var selector = attributes.evtSelector,
          expression = attributes.evtDelegate,
          expressionHandler = $parse(expression);

      element.on('click', function (e) {
        var targetNode, targetScope;

        targetNode = getTargetNode(element[0], e.target, selector);

        if (targetNode) {
          targetScope = angular.element(targetNode).scope();

          targetScope.$apply(function () {
            expressionHandler(targetScope);
          });
        }
      });
    }

    function getTargetNode(parent, child, selector) {
      if (!parent || !child) {
        return null;
      }

      if (!selector) {
        return child;
      }

      if (parent === child) {
        // we traveresed all the way up to the parent node, so return
        // null since the selector does not exist as a child
        return null;
      }

      // we cannot trust that child.nodeName is uppercase, 
      // so we make sure it is before doing the comparison
      if (child.nodeName.toUpperCase() === selector.toUpperCase()) {
        return child;
      }

      return getTargetNode(parent, child.parentNode, selector);
    }
  }
})();
I am puzzled by how you use item both inside and outside ng-repeat. 

Each iteration of ng-repeat has its own scope, so its own item. For instance, if items = [item1, item2], which item do you mean to use inside doSomething? 
The way it is used now, the item seen by that function will be another item on the outside scope. If this is the intention, this variable should be named differently:

&lt;ul evt-delegate="doSomething(outsideItem)" evt-selector="li"&gt;
  &lt;li ng-repeat="item in items"&gt;{{item.name}}&lt;/li&gt;
&lt;/ul&gt;




UPDATE. Having another look I see better what you are trying to achieve. Still I would improve design by making the directive more re-usable. 

You basically want to throw any HTML inside the directive and pick the model associated with event's target. The directive makes this model available on the scope of your expression doSomething(model).  Just like $event made available inside the ng-click. I would then mark this model as something special like:

&lt;ul evt-delegate="doSomething($my-target-model)"&gt;


Then it is the job of the directive to pick the right model and make it available under this name. This way I can change item to my-item inside ng-repeat without breaking things, so the directive is more encapsulated and re-usable.