43

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']);

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

4

3 に答える 3

63

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への依存関係としてモジュールを含めてみてください。そうすれば、他のアプリと通信できます。secondAppangular.module

于 2013-10-19T17:13:06.643 に答える
24

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

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

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

Angular の元の著者の 1 人である Misko Hevery は、この推奨事項 (この状況でサービスを使用すること) について、Angular Best Practicesというタイトルの講演で説明しています(このトピックについては 28:08 までスキップしてください。講演全体を見ることを強くお勧めします)。

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

于 2013-10-19T16:48:00.290 に答える
24

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

そしてここではControllerZero、呼び出しのトリガーとして使用される3 つのコントローラーprepForBroadcast

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

ハンドラーを使用して変更ControllerOneControllerTwoリッスンします。message$scope.$on

于 2013-10-19T17:50:26.297 に答える