43

我试图通过使用scope变量在第一个控制器中调用第二个控制器的方法。这是我的第一个控制器中的一种方法:

$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'

有没有办法调用上述方法?

编辑:

我使用以下方法同时加载两个应用程序;

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

我绝对可以在这里使用服务,但我想知道是否还有其他选择可以做到这一点!

4

3 回答 3

63

在两个控制器之间进行通信的最佳方法是使用事件。

范围文档

在此签出$on$broadcast$emit

在一般用例中, 的使用angular.element(catapp).scope()是为在角度控制器之外使用而设计的,例如在 jquery 事件中。

理想情况下,在您的使用中,您将在控制器 1 中编写一个事件:

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

在第二个控制器中,您只需执行

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

编辑:意识到这是两个模块之间的通信

您可以尝试将firstApp模块包含secondApp在您声明angular.module. 这样您就可以与其他应用程序进行通信。

于 2013-10-19T17:13:06.643 回答
24

每个控制器都有自己的范围,因此会导致您的问题。

拥有两个想要访问相同数据的控制器是您想要服务的典型标志。Angular 团队推荐将视图和服务粘合在一起的瘦控制器。特别是-“服务应该在控制器之间保持共享状态”。

令人高兴的是,有一段 15 分钟的精彩视频准确描述了这一点(通过服务进行控制器通信): 视频

Angular 的原作者之一 Misko Hevery 在他的题为Angular Best Practices的演讲中讨论了这个建议(在这种情况下使用服务) (这个话题请跳到 28:08,尽管我非常强烈建议观看整个演讲)。

您可以使用事件,但它们只是为想要解耦的两方之间的通信而设计的。在上面的视频中,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用作触发器来调用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;
    });
}

和监听使用处理程序ControllerOne进行更改。ControllerTwomessage$scope.$on

于 2013-10-19T17:50:26.297 回答