2013-02-12 4 views
19

ローカルスコープに一部の機能をバインドするディレクティブが$scope.$onです。

同じ関数を1回の呼び出しで複数のイベントにバインドすることはできますか?

app.directive('multipleSadness', function() { 
    return { 
     restrict: 'C', 
     link: function(scope, elem, attrs) { 
      scope.$on('event:auth-loginRequired event:auth-loginSuccessful', function() { 
       console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks'); 
      }); 
     } 
    }; 
}); 

をしかし、これは動作しません:

理想的には私はこのような何かをすることができると思います。カンマ区切りのイベント名文字列を['event:auth-loginRequired', 'event:auth-loginConfirmed']に置き換えた同じ例でも、wrkは実行されません。仕事を何

はこれです:

app.directive('multipleSadness', function() { 
    return { 
     restrict: 'C', 
     link: function(scope, elem, attrs) { 

      scope.$on('event:auth-loginRequired', function() { 
       console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks'); 
      }); 
      scope.$on('event:auth-loginConfirmed', function() { 
       console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks'); 
      }); 
     } 
    }; 
}); 

しかし、これは理想的ではありません。

同じ機能に複数のイベントをバインドすることは可能ですか?

答えて

11

はい。このように:

app.directive('multipleSadness', function() { 
    return { 
     restrict: 'C', 
     link: function(scope, elem, attrs) { 

      function sameFunction(eventId) { 
       console.log('Event: ' + eventId + '. The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks.'); 
      } 

      scope.$on('event:auth-loginRequired', function() {sameFunction('auth-loginRequired');}); 
      scope.$on('event:auth-loginConfirmed', function() {sameFunction('auth-loginConfirmed');}); 
     } 
    }; 
}); 

しかし、あなたがすることができますので、あなたはすべきではありません:)。イベントが別のリスナーに伝播し続け、イベントが別のリスナーで処理される場合は、これを行うケースがあります。これが唯一のリスナーになる場合は、同じイベントを放つ(またはブロードキャストする)必要があります。あなたは常に自分自身をロールバックでき、というバーリング

+0

イベントの伝播とイベントIDに関する追加情報をありがとう、これを知って私はなぜ私が尋ねるものはネイティブに可能ではないことを理解しています。イベントには異なるリスナーがありますが、この1人のリスナーは複数のイベントで同じアクションを実行する必要があります。 –

+0

考察の後、私はコードをもっと*角度*にリファクタリングしました。まだ2つのイベントがありますが、それらが異なるもの(リファクタリングで)を示すので、両方を同じ機能にバインドする理由はありません。ポインタをありがとう。 –

+0

全く問題ありません。お役に立てて嬉しいです。 – testing123

7

イベントはコールバックにデータを送信する可能性があり、複数のイベントをリスンすると、どのデータがどのイベントから来たのかわからないため、これは可能ではないと思います。私はこのような何かをやっているだろう

function listener() { 
    console.log('event fired'); 
} 
scope.$on('event:auth-loginRequired', listener); 
scope.$on('event:auth-loginConfirmed', listener); 
13

AngularJSが結合複数のイベントをサポートしていませんが、あなたがこのような何かを行うことができます。

var handler = function() { ... } 
angular.forEach("event:auth-loginRequired event:auth-loginConfirmed".split(" "), function (event) { 
    scope.$on(event, handler); 
}); 
+1

[event:auth-loginRequired '、' event:auth-loginConfirmed ']の代わりに "event:auth-loginRequired event:auth-loginConfirmed" .split( "")を使用する理由はありますか? –

+0

@ RyanO'Neill特別な理由はありません=)ただ一つの文字列を持つのはちょうど[''、 ''、 ''、...]よりもきれいです。また、OPの例では、コンマで区切られた単一の文字列を使用していました。おかげさまで – bmleite

+2

JavaScriptはそれが何であっても、わたしが知っておくべき瞬間を見逃していないことを確かめたかったのです。 –

27

他の回答(アンダースEkdahl)それらのいずれかを選ぶ... 100%正しいです...しかし...

// a hack to extend the $rootScope 
app.run(function($rootScope) { 
    $rootScope.$onMany = function(events, fn) { 
     for(var i = 0; i < events.length; i++) { 
     this.$on(events[i], fn); 
     } 
    } 
}); 

app.directive('multipleSadness', function() { 
    return { 
     restrict: 'C', 
     link: function(scope, elem, attrs) { 
      scope.$onMany(['event:auth-loginRequired', 'event:auth-loginSuccessful'], function() { 
       console.log('The Ferrari is to a Mini what AngularJS is to ... other JavaScript frameworks'); 
      }); 
     } 
    }; 
}); 

実際に.split(',')を実行したければ、それは実装の詳細です。また、$ rootScopeと同様

+1

これを私がこれを使用できるPRとして提出する必要があります。たぶん私はあなたの信用を取るだろう。 –

+1

各繰り返しの長さをチェックするのは非常に高価です。変数に長さを代入する方が良いです –

+7

@VerdiErelErgün "非常に高価です"?ヒットするために1ミリ秒あたり何回これを実行しますか?いくつかのバインディングを設定するための一回限りの呼び出しです。マイクロ最適化は実際にはここでのポイントではありませんでした...しかし、はい、for(var i = 0、len = events.length; i

1

$ onMany(ベン・レッシュ@から溶液)それがメソッドに$を拡張することが可能です:。

var $onOrigin = $rootScope.$on; 

$rootScope.$on = function(names, listener) { 
    var self = this; 

    if (!angular.isArray(names)) { 
    names = [names]; 
    } 

    names.forEach(function(name) { 
    $onOrigin.call(self, name, listener); 
    }); 

}; 

hereから取りました。

+1

子スコープに変更された関数も継承させたい場合は、 '$ rootScope .__ proto __。$ on'(または' $ rootScope.constructor.prototype。$ on')を変更する必要があります。 – cipak

関連する問題