71

I know that I can get access to the click event from ng-click if I pass in the $event object like so:

<button ng-click="myFunction($event)">Give me the $event</button>

<script>
  function myFunction (event) {
    typeof event !== "undefined" // true
  }
</script>

It's a little bit annoying having to pass $event explicitly every time. Is it possible to set ng-click to somehow pass it to the function by default?

4

4 回答 4

65

看一下ng-click指令源:

...
compile: function($element, attr) {
  var fn = $parse(attr[directiveName]);
  return function(scope, element, attr) {
    element.on(lowercase(name), function(event) {
      scope.$apply(function() {
        fn(scope, {$event:event});
      });
    });
  };
}

它显示event对象是如何被传递ng-click表达式的,使用$event作为参数的名称。这是由 $parse 服务完成的,它不允许参数渗入目标范围,这意味着答案是否定的,您不能以$event任何其他方式访问对象,只能通过回调参数。

于 2014-01-13T21:27:23.547 回答
45

在 中添加一个$eventng-click例如:

<button type="button" ng-click="saveOffer($event)" accesskey="S"></button>

然后jQuery.Event传递给回调:

在此处输入图像描述

于 2014-08-05T07:39:37.180 回答
11

正如其他人所说,你实际上不能严格按照你的要求去做。也就是说,Angular 框架可用的所有工具实际上也可供您使用!这意味着您实际上可以编写自己的元素并自己提供此功能。我写了其中一个作为示例,您可以在以下 plunkr ( http://plnkr.co/edit/Qrz9zFjc7Ud6KQoNMEI1 ) 中看到。

其中的关键部分是我定义了一个“可点击”元素(如果您需要较旧的 IE 支持,请不要这样做)。在看起来像的代码中:

<clickable>
  <h1>Hello World!</h1>
</clickable>

然后我定义了一个指令来获取这个可点击元素并将它变成我想要的(自动设置我的点击事件的东西):

app.directive('clickable', function() {
    return {
        transclude: true,
        restrict: 'E',
        template: '<div ng-transclude ng-click="handleClick($event)"></div>'
    };
});

最后在我的控制器中,我准备好了点击事件:

$scope.handleClick = function($event) {
    var i = 0;
};

现在,值得一提的是,它硬编码了处理点击事件的方法的名称。如果你想消除这种情况,你应该能够为指令提供你的点击处理程序的名称和“tada”——你有一个可以使用的元素(或属性),而不必再次注入“$event”。

希望有帮助!

于 2014-01-13T21:39:14.250 回答
2

我不建议这样做,但您可以覆盖该ngClick指令以执行您正在寻找的操作。这不是说,你应该。

考虑到原始实现:

compile: function($element, attr) {
  var fn = $parse(attr[directiveName]);
  return function(scope, element, attr) {
    element.on(lowercase(name), function(event) {
      scope.$apply(function() {
        fn(scope, {$event:event});
      });
    });
  };
}

我们可以这样做来覆盖它:

// Go into your config block and inject $provide.
app.config(function ($provide) {

  // Decorate the ngClick directive.
  $provide.decorator('ngClickDirective', function ($delegate) {

    // Grab the actual directive from the returned $delegate array.
    var directive = $delegate[0];

    // Stow away the original compile function of the ngClick directive.
    var origCompile = directive.compile;

    // Overwrite the original compile function.
    directive.compile = function (el, attrs) {

      // Apply the original compile function. 
      origCompile.apply(this, arguments);

      // Return a new link function with our custom behaviour.
      return function (scope, el, attrs) {

        // Get the name of the passed in function. 
        var fn = attrs.ngClick;

        el.on('click', function (event) {
          scope.$apply(function () {

            // If no property on scope matches the passed in fn, return. 
            if (!scope[fn]) {
              return;
            }

            // Throw an error if we misused the new ngClick directive.
            if (typeof scope[fn] !== 'function') {
              throw new Error('Property ' + fn + ' is not a function on ' + scope);
            }

            // Call the passed in function with the event.
            scope[fn].call(null, event);

          });
        });          
      };
    };    

    return $delegate;
  });
});

然后你会像这样传递你的函数:

<div ng-click="func"></div>

相对于:

<div ng-click="func()"></div>

jsBin:http: //jsbin.com/piwafeke/3/edit

就像我说的那样,我建议这样做,但这是一个概念证明,向您展示,是的 - 您实际上可以覆盖/扩展/增强内置角度行为以满足您的需求。无需深入挖掘原始实现。

如果你决定走这条路,请小心使用它(虽然这很有趣)。

于 2014-07-23T14:47:57.373 回答