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

时间:2014-02-21 08:35:16

标签: jquery angularjs events javascript-events angularjs-directive

我在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);
});

我想在点击链接时触发此事件。

如果我在replace指令上将false属性设置为sample,则可行。我想这是因为在触发事件时,元素sample不再存在,因此它将被内部模板替换。

那么,我该如何做到这一点?

按照以下答案的建议,这样做不会达到我的目的:

$($element).trigger("myEvent.sample", [something]);

2 个答案:

答案 0 :(得分:16)

请在下面找到小提琴

fiddle

触发器是一个jquery函数,可以在适当的处理程序上运行。

$(element).trigger("myEvent.sample");

希望这有帮助

答案 1 :(得分:4)

这里更新了小提琴:http://jsfiddle.net/3u3zh/1/

有几点值得注意:

  1. 由于角度转换DOM的方式,我建议在主体上附加所有自定义侦听器,然后按事件目标过滤它们。 $('body').on('myEvent.sample', 'target-selector-expr', handler)正是这样做的。例如,如果在ngRepeat ed元素上使用自定义事件侦听器,则不会执行处理程序,因为在尝试将事件附加到它们时这些元素不存在。

  2. 在触发事件时,似乎有点缺乏角度的jqLit​​e实现功能。因此,我在jQuery(sample)中包含了$($element)个元素,因为否则附加数据将无法到达处理程序。

  3. 最终模板:

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