サービスへのコントローラー注入

概要

コントローラーへ依存するものとしてサービスを使用するのは、 他のサービスに依存するものとしてサービスを使用するのに非常によく似ています。

JavaScriptは動的な型付け言語であるため、 DIは静的な型(静的な型付け言語のように)から、注入するサービスを読み取る事が出来ません。 そのため、注入されるサービス名の文字列を含んだ配列の$injectプロパティを使用することで、 サービス名を指定することが出来るようになっています。 サービス名は、Angularで登録された対応するサービスIDと一致しなければいけません。 配列内のサービスの順番(サービスIDの項目の順番)は、ファクトリー関数を呼び出す際に使用されます。 ファクトリー関数内の引数の名前は自由に指定出来ますが、慣習によってサービスIDに一致させておくと、 後述するメリットを享受することが出来ます。(翻訳に自信なし)

function myController($loc, $log) {
  this.firstMethod = function() {
    // $locationサービスを使用
    $loc.setHash();
  };
  this.secondMethod = function() {
    // $logサービスを使用
    $log.info('...');
  };
}
// どのサービスを注入するか?
myController.$inject = ['$location', '$log'];
<!doctype html>
<html ng-app="MyServiceModule">
  <head>
    <script src="http://code.angularjs.org/1.2.3/angular.min.js"></script>
    <script src="script.js"></script>
  </head>
  <body>
    <div ng-controller="myController">
      <p>Let's try this simple notify service, injected into the controller...</p>
      <input ng-init="message='test'" ng-model="message" >
      <button ng-click="callNotify(message);">NOTIFY</button>
      <p>(you have to click 3 times to see an alert)</p>
    </div>
  </body>
</html>
angular.
 module('MyServiceModule', []).
 factory('notify', ['$window', function(win) {
    var msgs = [];
    return function(msg) {
      msgs.push(msg);
      if (msgs.length == 3) {
        win.alert(msgs.join("\n"));
        msgs = [];
      }
    };
  }]);

function myController(scope, notifyService) {
  scope.callNotify = function(msg) {
    notifyService(msg);
  };
}

myController.$inject = ['$scope','notify'];
it('should test service', function() {
  expect(element(':input[ng\:model="message"]').val()).toEqual('test');
});
<!doctype html>
<html ng-app="MyServiceModule">
  <head>
    <script src="http://code.angularjs.org/1.2.3/angular.min.js"></script>
<script>angular.
 module('MyServiceModule', []).
 factory('notify', ['$window', function(win) {
    var msgs = [];
    return function(msg) {
      msgs.push(msg);
      if (msgs.length == 3) {
        win.alert(msgs.join("\n"));
        msgs = [];
      }
    };
  }]);

function myController(scope, notifyService) {
  scope.callNotify = function(msg) {
    notifyService(msg);
  };
}

myController.$inject = ['$scope','notify'];
</script>
  </head>
  <body>
    <div ng-controller="myController">
      <p>Let's try this simple notify service, injected into the controller...</p>
      <input ng-init="message='test'" ng-model="message" >
      <button ng-click="callNotify(message);">NOTIFY</button>
      <p>(you have to click 3 times to see an alert)</p>
    </div>
  </body>
</html>

暗黙の依存性注入(DI)

AngularのDIの新機能では、引数の名前から依存性を決定することが可能です。 上記のサンプルを、この$window、$scope、通知サービスを暗黙の依存性を使用したものに書き換えてみましょう。

注意:このサンプルは、ソースコードを圧縮(minify)すると動作しなくなる可能性があります。 詳細については、ガイドのコンセプト概要 - UIロジックの追加: コントローラーの最後の段落を参照してください。

<!doctype html>
<html ng-app="MyServiceModuleDI">
  <head>
    <script src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
    <script src="script.js"></script>
  </head>
  <body>
    <div ng-controller="myController">
      <p>Let's try the notify service, that is implicitly injected into the controller...</p>
      <input ng-init="message='test'" ng-model="message">
      <button ng-click="callNotify(message);">NOTIFY</button>
      <p>(you have to click 3 times to see an alert)</p>
    </div>
  </body>
</html>
angular.
 module('MyServiceModuleDI', []).
 factory('notify', function($window) {
    var msgs = [];
    return function(msg) {
      msgs.push(msg);
      if (msgs.length == 3) {
        $window.alert(msgs.join("\n"));
        msgs = [];
      }
    };
  });

function myController($scope, notify) {
  $scope.callNotify = function(msg) {
    notify(msg);
  };
}
<!doctype html>
<html ng-app="MyServiceModuleDI">
  <head>
    <script src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
<script>angular.
 module('MyServiceModuleDI', []).
 factory('notify', function($window) {
    var msgs = [];
    return function(msg) {
      msgs.push(msg);
      if (msgs.length == 3) {
        $window.alert(msgs.join("\n"));
        msgs = [];
      }
    };
  });

function myController($scope, notify) {
  $scope.callNotify = function(msg) {
    notify(msg);
  };
}
</script>
  </head>
  <body>
    <div ng-controller="myController">
      <p>Let's try the notify service, that is implicitly injected into the controller...</p>
      <input ng-init="message='test'" ng-model="message">
      <button ng-click="callNotify(message);">NOTIFY</button>
      <p>(you have to click 3 times to see an alert)</p>
    </div>
  </body>
</html>

ただし、コードを圧縮化する予定がある場合、それによって変数名が変更されてしまうため、 $injectプロパティを使用するなどの明示的な依存性の指定が必要になります。

関連トピック

  • Angular Service API

 Back to top

© 2017 Google
Licensed under the Creative Commons Attribution License 3.0.

このページは、ページトップのリンク先のAngularJS公式ドキュメント内のページを翻訳した内容を基に構成されています。 下記の項目を確認し、必要に応じて公式のドキュメントをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。

  • AngularJSの更新頻度が高いため、元のコンテンツと比べてドキュメントの情報が古くなっている可能性があります。
  • "訳注:"などの断わりを入れた上で、日本人向けの情報やより分かり易くするための追記を行っている事があります。