web-dev-qa-db-ja.com

jQueryを使用してAngularJS要素ディレクティブにイベントをバインドする

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]);
7
Milad Naseri

以下のフィドルを見つけてください

フィドル

トリガーは、適切なハンドラーで動作するjquery関数です。

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

お役に立てれば

16
Sai

ここに更新されたフィドルがあります: http://jsfiddle.net/3u3zh/1/

注目に値するいくつかのポイントがあります:

  1. angularはDOMを変換する方法があるため、すべてのカスタムリスナーをbodyにアタッチし、イベントターゲットでフィルタリングすることをお勧めします。$('body').on('myEvent.sample', 'target-selector-expr', handler)は、まさにそれを行います。たとえば、 ngRepeated要素でカスタムイベントリスナーを使用すると、それらの要素にイベントをアタッチしようとしたときにこれらの要素が存在しないため、ハンドラーは実行されません。

  2. AngularのjqLit​​e実装は、イベントをトリガーするときの機能がいくらか不足しているようです。したがって、sampleの要素をjQuery($($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);
    });
});
4
package