Ad

Is There Any Way To Do This With A Directive?

- 1 answer

I have no problem getting the $scope function referenced in the directive attribute to run. The problem is I need to capture the element that was touched in the directive and pass it to the function in the attribute. I haven't figure out how to do that. Isolating the scope in the directives will throw an error because there's 2 directives trying to act on the same element.

With the below code I am getting $event as undefined and an error of course. Any way to achieve what I want? Or maybe there's a better way?

<li class="list-group-item row" data-touchstart="darkenBackground($event)" data-touchend="lightenBackground($event)">

..

angular.module('myNotes')
    .directive('touchstart', [function () {
        return {
            restrict: 'A',
            link: function (scope, elem, attrs) {
                elem.bind('touchstart', function(e) {
                    e.preventDefault();
                    scope.$apply(attrs.touchstart);
                });
            }
        };
    }]);

angular.module('myNotes')
    .controller('notesCtrl', ['$scope', 'Site',
        function($scope, Site) {
            Site.setTitle('My Notes');
            Site.setActiveNavLink('myNotes');

            $scope.darkenBackground = function($event) {
                angular.element($event.currentTarget)
                    .css('background-color', '#eee');
            };
            $scope.lightenBackground = function($event) {
                angular.element($event.currentTarget)
                    .css('background-color', '#fff');
            }
    }]);
Ad

Answer

Here's the issue:

scope.$apply(attrs.touchstart);

When you call scope.$apply directly on an angular expression (which is what attrs.touchstart is), it will automatically evaluate that expression against scope, so scope.$event (which is undefined) is passed to the callback.

To pass the event to the callback, you can use the second parameter (called "locals") of scope.$eval to temporarily include an $event property on the scope while evaluating the expression.

return {
  restrict: 'A',
  link: function (scope, elem, attrs) {
    elem.bind('touchstart', function (e) {
      e.preventDefault();
      scope.$apply(function () {
        scope.$eval(attrs.touchstart, {$event: e});
      });
    });
  }
};
Ad
source: stackoverflow.com
Ad