web-dev-qa-db-ja.com

AngularJSの「スコープ」を使用して別のコントローラーからコントローラーのメソッドを呼び出す

scope変数を使用して、最初のコントローラーで2番目のコントローラーのメソッドを呼び出そうとしています。これは私の最初のコントローラーのメソッドです:

$scope.initRestId = function(){
        var catapp = document.getElementById('SecondApp');
        var catscope = angular.element(catapp).scope();
        catscope.rest_id = $scope.user.username;
        catscope.getMainCategories();
    }; 

rest_idの値を設定できますが、何らかの理由でgetMainCategoriesを呼び出すことはできません。コンソールには次のエラーが表示されます。

TypeError:オブジェクト#にはメソッド 'getMainCategories'がありません

上記のメソッドを呼び出す方法はありますか?

編集:

次のアプローチを使用して、2つのアプリを同時に読み込みました。

angular.bootstrap(document.getElementById('firstAppID'), ['firstApp']);
angular.bootstrap(document.getElementById('secondAppID'), ['secondApp']);

ここでは間違いなくサービスを使用できますが、同じことを行う他のオプションがあるかどうかを知りたかったです!

43
Arif Nadeem

2つのコントローラー間で通信するための最善の方法は、イベントを使用することです。

スコープドキュメント

このチェックアウトでは、$on$broadcast、および$emitを確認します。

一般的な使用例では、angular.element(catapp).scope()の使用法は、jqueryイベント内など、angularコントローラーの外部で使用するために設計されました。

理想的には、コントローラー1で次のようにイベントを作成します。

$scope.$on("myEvent", function (event, args) {
   $scope.rest_id = args.username;
   $scope.getMainCategories();
});

そして、2番目のコントローラーでは、

$scope.initRestId = function(){
   $scope.$broadcast("myEvent", {username: $scope.user.username });
};

編集:2つのモジュール間の通信であることがわかりました

firstAppモジュールを、angular.moduleを宣言するsecondAppへの依存関係として含めてみてください。そうすれば、他のアプリと通信できます。

ここに良いデモがあります Fiddle $scope.$onを介してディレクティブおよび他のコントローラーで共有サービスを使用する方法

HTML

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

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

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

<my-component ng-model="message"></my-component>

JS

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;
});

同様に、共有サービスをディレクティブで使用できます。コントローラーセクションをディレクティブに実装し、$scope.$onを使用できます

myModule.directive('myComponent', function(mySharedService) {
    return {
        restrict: 'E',
        controller: function($scope, $attrs, mySharedService) {
            $scope.$on('handleBroadcast', function() {
                $scope.message = 'Directive: ' + mySharedService.message;
            });
        },
        replace: true,
        template: '<input>'
    };
});

そして、ControllerZeroprepForBroadcastを呼び出すトリガーとして使用される3つのコントローラー

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;
    });
}

ControllerOneおよびControllerTwo listen messageは、$scope.$onハンドラーを使用して変更されます。

25
Maxim Shoustin

各コントローラーには独自のスコープがあるため、問題が発生しています。

同じデータへのアクセスを必要とする2つのコントローラーを持つことは、サービスが必要な典型的な兆候です。 angularチームは、ビューとサービスをつなぐだけのシンコントローラーを推奨しています。そして具体的には、「サービスはコントローラー間で共有状態を保持する必要があります」。

幸いなことに、これを正確に説明するニースの15分のビデオがあります(サービスを介したコントローラー通信): video

Angularの原作者の一人であるMisko Heveryは、この推奨事項(この状況でサービスを使用すること)について Angular Best Practices (このトピックについては28:08までスキップしてください。トーク全体を視聴することをお勧めします)。

イベントを使用できますが、それらは分離したい2つのパーティ間の通信用にのみ設計されています。上記のビデオでは、Miskoがアプリをより脆弱にする方法を説明しています。 「ほとんどの場合、サービスを注入して直接通信を行うことが好まれ、より堅牢です」。 (53:37から始まる上記のリンクをチェックして、彼がこれについて話しているのを聞いてください)

24
KayakDave