591

あるコントローラーで別のコントローラーを使用することはできますか?

例えば:

この HTML ドキュメントは、MessageCtrlコントローラによって配信されたメッセージをmessageCtrl.jsファイルに出力するだけです。

<html xmlns:ng="http://angularjs.org/">
<head>
    <meta charset="utf-8" />
    <title>Inter Controller Communication</title>
</head>
<body>
    <div ng:controller="MessageCtrl">
        <p>{{message}}</p>
    </div>

    <!-- Angular Scripts -->
    <script src="http://code.angularjs.org/angular-0.9.19.js" ng:autobind></script>
    <script src="js/messageCtrl.js" type="text/javascript"></script>
</body>
</html>

コントローラ ファイルには、次のコードが含まれています。

function MessageCtrl()
{
    this.message = function() { 
        return "The current date is: " + new Date().toString(); 
    };
}

現在の日付を単純に出力します。

DateCtrl特定の形式で日付を に戻す別のコントローラーを追加する場合、これをMessageCtrl行うにはどうすればよいでしょうか? DI フレームワークは、サービスに関心がXmlHttpRequestsあり、サービスにアクセスしているようです。

4

14 に答える 14

710

コントローラー間で通信する方法は複数あります。

最良の方法は、おそらくサービスを共有することです:

function FirstController(someDataService) 
{
  // use the data service, bind to template...
  // or call methods on someDataService to send a request to server
}

function SecondController(someDataService) 
{
  // has a reference to the same instance of the service
  // so if the service updates state for example, this controller knows about it
}

別の方法は、スコープでイベントを発行することです。

function FirstController($scope) 
{
  $scope.$on('someEvent', function(event, args) {});
  // another controller or even directive
}

function SecondController($scope) 
{
  $scope.$emit('someEvent', args);
}

どちらの場合も、任意のディレクティブと通信できます。

于 2012-02-23T05:59:47.110 に答える
123

このフィドルを参照してください: http://jsfiddle.net/simpulton/XqDxG/

次のビデオもご覧ください:コントローラー間の通信

HTML:

<div ng-controller="ControllerZero">
  <input ng-model="message" >
  <button ng-click="handleClick(message);">LOG</button>
</div>

<div ng-controller="ControllerOne">
  <input ng-model="message" >
</div>

<div ng-controller="ControllerTwo">
  <input ng-model="message" >
</div>

JavaScript:

var myModule = angular.module('myModule', []);
myModule.factory('mySharedService', function($rootScope) {
  var sharedService = {};

  sharedService.message = '';

  sharedService.prepForBroadcast = function(msg) {
    this.message = msg;
    this.broadcastItem();
  };

  sharedService.broadcastItem = function() {
    $rootScope.$broadcast('handleBroadcast');
  };

  return sharedService;
});

function ControllerZero($scope, sharedService) {
  $scope.handleClick = function(msg) {
    sharedService.prepForBroadcast(msg);
  };

  $scope.$on('handleBroadcast', function() {
    $scope.message = sharedService.message;
  });        
}

function ControllerOne($scope, sharedService) {
  $scope.$on('handleBroadcast', function() {
    $scope.message = 'ONE: ' + sharedService.message;
  });        
}

function ControllerTwo($scope, sharedService) {
  $scope.$on('handleBroadcast', function() {
    $scope.message = 'TWO: ' + sharedService.message;
  });
}

ControllerZero.$inject = ['$scope', 'mySharedService'];        

ControllerOne.$inject = ['$scope', 'mySharedService'];

ControllerTwo.$inject = ['$scope', 'mySharedService'];
于 2012-08-07T13:40:05.850 に答える
52

以下は、サービス データを共有する 2 つのコントローラーの 1 ページの例です。

<!doctype html>
<html ng-app="project">
<head>
    <title>Angular: Service example</title>
    <script src="http://code.angularjs.org/angular-1.0.1.js"></script>
    <script>
var projectModule = angular.module('project',[]);

projectModule.factory('theService', function() {  
    return {
        thing : {
            x : 100
        }
    };
});

function FirstCtrl($scope, theService) {
    $scope.thing = theService.thing;
    $scope.name = "First Controller";
}

function SecondCtrl($scope, theService) {   
    $scope.someThing = theService.thing; 
    $scope.name = "Second Controller!";
}
    </script>
</head>
<body>  
    <div ng-controller="FirstCtrl">
        <h2>{{name}}</h2>
        <input ng-model="thing.x"/>         
    </div>

    <div ng-controller="SecondCtrl">
        <h2>{{name}}</h2>
        <input ng-model="someThing.x"/>             
    </div>
</body>
</html>

また、こちら: https://gist.github.com/3595424

于 2012-09-02T06:51:53.823 に答える
33

コントローラー間でデータを共有したり関数を呼び出したりするためにイベントを発行およびブロードキャストすることを検討している場合は、このリンクzbynourを見て、 (最大投票数で回答) で回答を確認してください。私は彼の答えを引用しています!!!

firstCtrl のスコープが secondCtrl スコープの親である場合、コードは firstCtrl の $emit を $broadcast に置き換えることで機能するはずです。

function firstCtrl($scope){
    $scope.$broadcast('someEvent', [1,2,3]);
}

function secondCtrl($scope){
    $scope.$on('someEvent', function(event, mass) {console.log(mass)});
}

スコープ間に親子関係がない場合は、$rootScope をコントローラーに注入し、すべての子スコープ (つまり、secondCtrl) にイベントをブロードキャストできます。

function firstCtrl($rootScope){
    $rootScope.$broadcast('someEvent', [1,2,3]);
}

最後に、イベントを子コントローラーから上位のスコープにディスパッチする必要がある場合は、$scope.$emit を使用できます。firstCtrl のスコープが secondCtrl スコープの親である場合:

function firstCtrl($scope){
    $scope.$on('someEvent', function(event, data) { console.log(data); });
}

function secondCtrl($scope){
    $scope.$emit('someEvent', [1,2,3]);
}
于 2014-10-15T13:26:05.380 に答える
24

さらに2つのフィドル:(非サービスアプローチ)

1)$scope親子コントローラの場合 - 親コントローラを使用してイベントを発行/ブロードキャストします。 http://jsfiddle.net/laan_sachin/jnj6y/

2)$rootScope関連のないコントローラ間での使用。 http://jsfiddle.net/VxafF/

于 2012-10-07T17:07:39.027 に答える
17

イベントがスコープ階層を上下にバブルし、複雑なアプリケーションのパフォーマンスボトルに簡単に低下する可能性があるため、実際にエミットとブロードキャストを使用することは非効率的です。

サービスの利用をお勧めします。これが私のプロジェクトの1つであるhttps://gist.github.com/3384419に最近実装した方法です。

基本的な考え方-pub-sub/eventバスをサービスとして登録します。次に、イベント/トピックをサブスクライブまたは公開する必要がある場所に、そのイベントバスを挿入します。

于 2012-08-18T04:32:39.167 に答える
5

私もこの方法を知っています。

angular.element($('#__userProfile')).scope().close();

しかし、Angular コードで jQuery セレクターを使用するのが好きではないため、あまり使用しません。

于 2013-07-16T13:45:25.017 に答える