it-swarm.com.ru

Вызовите метод контроллера из другого контроллера, используя 'scope' в AngularJS

Я пытаюсь вызвать метод второго контроллера в первом контроллере, используя переменную 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: Object # не имеет метода getMainCategories

Есть ли способ вызвать вышеуказанный метод?

Edit:

Я использовал следующий подход для загрузки двух приложений одновременно;

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

Я мог бы определенно воспользоваться услугой здесь, но я хотел знать, есть ли другие варианты сделать то же самое!

43
Arif Nadeem

Наилучшим подходом для связи между двумя контроллерами является использование событий.

Scope Documentation

В этой проверке _$on_, _$broadcast_ и _$emit_.

В общем случае использования angular.element(catapp).scope() было разработано для использования вне angular контроллеров, как в событиях 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_. Таким образом, вы можете общаться с другим приложением.

62
Praveenram Balachandar

Вот хорошая демка в 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 и ​​ControllerTwo listen message изменяются с помощью $scope.$on обработчик.

25
Maxim Shoustin

Каждый контроллер имеет свою собственную область (ы), так что это вызывает вашу проблему.

Наличие двух контроллеров, которые хотят получить доступ к одним и тем же данным, является классическим признаком того, что вам нужен сервис . Команда angular рекомендует тонкие контроллеры, которые являются просто связующим звеном между представлениями и сервисами. А именно - "сервисы должны поддерживать общее состояние между контроллерами".

К счастью, есть хорошее 15-минутное видео, описывающее именно это (связь контроллера через сервисы): видео

Один из первоначальных авторов Angular, Миско Хевери, обсуждает эту рекомендацию (об использовании сервисов в этой ситуации) в своем выступлении под названием Angular Best Practices (перейдите к 28:08 по этой теме, хотя я очень высоко рекомендую смотреть весь разговор).

Вы можете использовать события, но они предназначены только для связи между двумя сторонами, которые хотят быть разъединенными. В приведенном выше видео Миско отмечает, как они могут сделать ваше приложение более хрупким. "Большую часть времени инъекционные услуги и прямое общение являются предпочтительными и более надежными" . (Посмотрите вышеуказанную ссылку, начиная с 53:37, чтобы услышать, как он говорит об этом)

24
KayakDave