使用ng-click自动传递$ event?

时间:2014-01-13 21:14:39

标签: javascript angularjs javascript-events angularjs-directive angularjs-ng-click

我知道如果我传递ng-click对象,我可以访问$event中的点击事件:

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

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

每次明确传递$event都有点烦人。是否可以将ng-click设置为默认以某种方式将其传递给函数?

4 个答案:

答案 0 :(得分:63)

查看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});
      });
    });
  };
}

It shows event对象如何传递传递到ng-click表达式,使用$event作为参数的名称。这是由$ parse服务完成的,它不允许参数流入目标范围,这意味着答案是否,你可以&# 39;以任何其他方式访问$event对象,但通过回调参数。

答案 1 :(得分:35)

$event添加ng-click,例如:

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

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

enter image description here

答案 2 :(得分:11)

正如其他人所说,你实际上不能严格按照你的要求去做。也就是说,角度框架可用的所有工具实际上也可供您使用!这意味着你实际上可以编写自己的元素并自己提供这个功能。我将其中一个作为示例编写,您可以在下面的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;
};

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

希望有所帮助!

答案 3 :(得分: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

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

请谨慎使用,如果您决定沿着这条路走下去(尽管这很有趣)。