使用jQuery在AngularJS元素指令上绑定事件

7

我有一个AngularJS指令:

module = angular.module("demoApp", [], null);
module.directive('sample', function () {
    return {
        restrict: "E",
        transclude: true,
        replace: true,
        template: "<div ng-transclude></div>",
        controller: function ($scope, $element) {
            this.act = function (something) {
                //problematic line HERE
                $element.trigger("myEvent.sample", [something]);
            };
        }
    };
})
.directive('item', function () {
    return {
        restrict: "E",
        require: "^sample",
        transclude: true,
        replace: true,
        template: "<a ng-transclude style='display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;'></a>",
        link: function (scope, element, attributes, parentController) {
            element.on("click", function () {
                parentController.act(this.innerText);
            });
        }
    }
});

而在我的HTML中,我这样使用它:

<sample id="myElement">
    <item>1</item>
    <item>2</item>
</sample>

将被渲染为:

<div ng-transclude="" id="myElement">
    <a ng-transclude="" style="display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;;display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;" class="ng-scope"><span class="ng-scope">1</span></a>
    <a ng-transclude="" style="display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;;display: inline-block; border: 1px solid crimson; margin: 2px; padding: 5px; color: crimson; text-decoration: none; background: #f5d0d0; cursor: pointer;" class="ng-scope"><span class="ng-scope">2</span></a>
</div>

我希望能够通过jQuery手动触发事件,并进行监听:
$("#myElement").on("myEvent.sample", function (e, something) {
    alert("click: " + something);
});

我希望每次单击链接时都触发此事件。 如果我在sample指令上将replace属性设置为false,它就可以工作。我猜这是因为在触发事件的时候,元素sample已经不存在了,因此它将被内部模板替换。 那么,我该如何实现这一点呢? 按照下面答案中的建议执行此操作将无法实现我的目的:
$($element).trigger("myEvent.sample", [something]);

函数链接:function($scope, $element){ $element.click(function(){alert('clicked'):});} - KoIIIeY
2个回答

16
请查看以下代码的fiddle链接: fiddle Trigger是一个jQuery函数,它将在正确的处理程序上工作。
$(element).trigger("myEvent.sample");

希望这能有所帮助


非常感谢您的努力。因此,您将得到接受。实际问题在于我使用的jQuery版本。我使用的是2.x版本。看到您的fiddle让我朝着正确的方向前进。 - Milad Naseri
@MiladNaseri 我不确定我是否理解你的意思。我已经使用Jquery 2.x更新了我的fiddle,它正在按预期工作。fiddle。你是指因为Jquery 2.x还有其他问题吗? - Sai
实际上是的。我刚刚查看了AngularJS文档,它明确表示在1.2.x版本中仍不支持jQuery 2.x的事件绑定。 - Milad Naseri

4
这是更新的 fiddle:http://jsfiddle.net/3u3zh/1/ 有几点值得注意:
  1. 由于 angular 转换 DOM 的方式,我建议在 body 上添加所有自定义监听器,然后通过事件目标进行过滤。 $('body').on('myEvent.sample', 'target-selector-expr', handler) 正好做到了这一点。例如,如果你在 ngRepeat 的元素上使用自定义事件监听器,则在尝试将事件附加到它们时,处理程序将不会执行,因为那些元素在那个时候不存在。

  2. 似乎 angular 的 jqLite 实现在触发事件时功能有些欠缺。因此,我包装了 jQuery 中的 sample 元素($($element)),否则附加的附加数据将无法到达处理程序。

最终模板:
<div ng-app="myApp">
  <sample id="myElement"><item>1</item><item>2</item></sample>
</div>

Js:

var myApp=angular.module('myApp',[]);
myApp.directive('sample', function () {
    return {
        restrict: "E",
        replace: true,
        transclude: true,
        template: "<div ng-transclude></div>",
        controller: function ($scope, $element) {
            this.act = function (something) {
               $($element).trigger("myEvent.sample", [something]);
            };
        }
    };
})
.directive('item', function () {
    return {
        restrict: "E",
        require: "^sample",
        transclude: true,
        template: "<a ng-transclude></a>",
        link: function (scope, element, attributes, parentController) {
            element.on("click", function(e) {
                parentController.act(this.innerHTML);
            });
        }
    }
})

$(document).ready(function(){
    $("body").on("myEvent.sample", '#myElement', function (e, something) {
        alert('clicked: ' + something);
    });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接