用ng-click自动传递$ event?


69

我知道,ng-click如果$event像这样传递对象,就可以访问click事件:

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

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

$event每次必须显式地通过都会有点烦人。是否可以设置ng-click为默认将其传递给函数?


10
我知道代码只是用于演示,而undefined应该是"undefined",否则该表达式在typeof返回字符串时将始终评估为false 。
法布里西奥磨砂

1
我想知道为什么您$event仍然需要。
更好的Oliver,2014年

6
@zeroflagL事件对象通常用于停止冒泡/传播。
Stewie 2014年

3
@StewiemyFunction是控制器的一部分。控制器不应该在乎UI。此外,简单的按钮没有默认操作。而且,Angular确实可以防止许多默认操作。因此,尽管您是对的,但是,很难想象一个好的用例。
更好的Oliver,2014年

1
@zeroflagL我有一个指令contextMenu,它为范围提供了几个函数(打开,关闭,切换),这些函数用特定的名称调用contextMenu,例如ng-click="account_menu.toggle()"。菜单本身位于其他元素中,例如<div context-menu="account_menu"></div>"。为了将菜单正确放置在名为的触发元素下方的页面上toggle(),我想访问ng-click$event.target元素,以便获取其坐标。让我知道是否有更简单的方法:)
Elise 2014年

Answers:


64

看看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服务完成的,该服务不允许参数渗入目标作用域,这意味着答案为no,您只能$event通过回调参数来访问对象。


41

a添加$eventng-click,例如:

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

然后将jQuery.Event传递给回调:

在此处输入图片说明


18
...除非这是OP试图不做的确切事情,除非我疯了。这篇文章的重点是访问$ event而不显式传递它……这似乎正是您在这里所做的。
dudewad

3
我(另一方面)可以忍受
svarog

7
在通过Google搜索如何传递$ event之后结束。与其他支持者相似,没有阅读原始问题:-|
JenonD '16

11

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

其中的关键部分是定义“可点击”元素(如果需要较旧的IE支持,则不要这样做)。在如下代码中:

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

然后,我定义了一个指令以接受此clickable元素并将其转换为我想要的(自动设置click事件的东西):

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

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

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

现在,值得说明的是,这对处理click事件的方法的名称进行了硬编码。如果要消除这种情况,则应该能够为指令提供单击处理程序的名称和“ tada”-您可以使用一个元素(或属性),而不必再次注入“ $ event”。

希望有帮助!


1
您必须使该handleClick事件可以传递一些,伙计:)
vbullinger

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>

jsBinhttp : //jsbin.com/piwafeke/3/edit

就像我说的,我建议您这样做,但这是一个概念证明,向您表明,是的-实际上,您可以覆盖/扩展/增强内置的角度特性以适应您的需求。无需深入研究原始实现。

如果您决定沿着这条路走,请小心使用(尽管这很有趣)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.