AngularJSのディレクティブにサービスを注入できますか?


234

以下のようなディレクティブにサービスを注入しようとしています:

 var app = angular.module('app',[]);
 app.factory('myData', function(){
     return {
        name : "myName"
     }
 });
 app.directive('changeIt',function($compile, myData){
    return {
            restrict: 'C',
            link: function (scope, element, attrs) {
                scope.name = myData.name;
            }
        }
 });

しかし、これは私にエラーを返していますUnknown provider: myDataProvider。誰かがコードを調べて、私が何か間違っているのかどうか教えてくださいませんか?

回答:


388

ディレクティブの注入を行うことができ、それは他の場所と同じように見えます。

app.directive('changeIt', ['myData', function(myData){
    return {
        restrict: 'C',
        link: function (scope, element, attrs) {
            scope.name = myData.name;
        }
    }
 }]);

13
コードを縮小した後でも機能するため、これはより良いソリューションだと思います。
czerasz 2013

5
戻り値{}の前に '_myData = myData'を追加してから、リンク関数内でオブジェクトを_myDataとして参照する必要がありました。
2013年

@Jellingに感謝します。私も同じことをしなければなりませんでした。なぜ誰かが私たちに理由を教えてくれるのだろうか...?
sfletche 2014年

6
ディレクティブに$ compileを挿入する特別な理由はありますか?どこでも使われていないようです。
gru

4
ディレクティブ呼び出しの外でリンク関数を作成したい場合に注入する解決策はありますか?
ThinkBonobo 2015年

19

ディレクティブ定義をからapp.moduleに変更しますapp.directive。それを除いて、すべてがうまく見えます。 ところで、ごくまれに、ディレクティブにサービスを挿入する必要があります。ディレクティブ(ビューの一部)にサービス(通常はデータソースまたはモデル)を注入する場合は、ビューとモデルの間に直接結合を作成しています。コントローラを使用してそれらを一緒に配線することにより、それらを分離する必要があります。

それはうまくいきます。私はあなたが何をしているのかよくわかりません。ここでそれは働いています。

http://plnkr.co/edit/M8omDEjvPvBtrBHM84Am


例を挙げてもらえますか
例外:

@例外コードをいじくり回せますか?私は見て、あなたのコードが機能しない理由を見ることができ、おそらくあなたがそれを修正するのを助けます。
ganaraj 2013年

@Exceptionは、コードが機能していることを示す機能するプランクを追加しました。
ganaraj 2013年

3
私は何かを発見しました:関数パラメーターでインジェクションを定義しても、function($location) { ...実際$locationには関数内で参照しない場合、AngularJSはインジェクションを実行しません。この動作に気付くのは、デバッガー内だけです。
Walter Stabosz 2013

13
私はあなたの「結合された」コメントに同意するかどうかわかりません。コントローラーとサービスは既にグローバルに結合しています。実行時にサービスの実装をプログラムで置き換えることはできません。つまり、単一のコントローラーが単一のサービスを取得します。ただし、ディレクティブはページ上のタグごとに構成を分離しているため、異なるディレクティブインスタンスに対して異なるサービスを有効にする可能性があります。これはデカップリングが少ないように思えます。
モグラビ男2013年

11

$ injectサービスを使用して、好きなサービスを取得することもできます。事前にサービス名はわからないが、サービスインターフェースは知っている場合に便利です。たとえば、ngResourceエンドポイントにテーブルをプラグインするディレクティブ、または任意のAPIエンドポイントと相互作用する一般的なレコード削除ボタン。すべてのコントローラーまたはデータソースのテーブルディレクティブを再実装する必要はありません。

template.html

<div my-directive api-service='ServiceName'></div>

my-directive.directive.coffee

angular.module 'my.module'
  .factory 'myDirective', ($injector) ->
    directive = 
      restrict: 'A'
      link: (scope, element, attributes) ->
        scope.apiService = $injector.get(attributes.apiService)

これで、「匿名」サービスが完全に利用可能になります。たとえばngResourceの場合、標準のngResourceインターフェースを使用してデータを取得できます

例えば:

scope.apiService.query((response) ->
  scope.data = response
, (errorResponse) ->
  console.log "ERROR fetching data for service: #{attributes.apiService}"
  console.log errorResponse.data
)

この手法は、特にAPIエンドポイントと相互作用する要素を作成するときに非常に役立つことがわかりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.