AngularJS + Ionic - how to call method on the second controller from first controller with deffer promise?

8.9k Views Asked by At

I need to call method for initialization user setting values (which are set to rootscope) from second cotroller in method of the first controller.

After the values are succesfully set to rootscope return premise and continue in executing of the second method of the first controller.

I tried it with emit and broadcast examples, but without luck.

Could somebody please give me a advice how to do it correctly?

I am on Angular 1.2 and Ionic 1, beta 13

Many thanks for any help.

Template:

<ion-view title="{{ 'DAYS_RESULTS' | translate }}" >
    <ion-content ng-controller="DailyStatsCtrl" ng-init="setData()">

Code:

// First cotroller call setData in ng-init

angular.module('starter')
// Controller definition
.controller('DailyStatsCtrl', function($scope, $rootScope, $ionicSlideBoxDelegate, $timeout , $ionicLoading , $q, $translate, DialsComputeService, cordova, LocalStorService,  $ionicPopup, $state, $ionicNavBarDelegate, testService, $ionicPlatform) {


        $scope.setData = function() {
            $ionicPlatform.ready(function() {
                $timeout(function() {
                    $scope.$emit("onSomething", "");
                    alert("TEST");
                }, 1000);
            });
        }; 

In the second controller:

angular.module('starter')
// Controller definition
.controller('SettingsCtrl', function($scope, $rootScope, $ionicLoading, $ionicPlatform, LocalStorService, $timeout, $translate, $ionicPopup, $state, $ionicNavBarDelegate) {

    $scope.getUserSettigns = function() {
        alert("received");
        $scope.test = 'event received';
    }
    $scope.$on('onSomething', function(e) {
        $scope.getUserSettigns();
    });
3

There are 3 best solutions below

5
On

I have literally just done some event emitting. It is a pain but here is down low:

$scope.$broadcast

This will emit events down the children scopes

Angular Doc Definition:

Dispatches an event name downwards to all child scopes (and their children)


$scope.$emit

This will emit events up to the parent scopes

Angular Doc Definition:

Dispatches an event name upwards through the scope hierarchy


Me and my collegue believe that this is the best method. But also I believe this is the most reliable:

In the controller / service that is dispatching the event inject the $rootScope and use $broadcast

.service('DispatchEvent', ['$rootScope', function ($rootScope) {
    $rootScope.$broadcast('someEvent');
}]);

On the controller / service that is receiving the event, inject the $scope and use $on

.controller('ReceivingEventsController', ['$scope', function ($scope) { 
     $scope.$on('someEvent', function (e) { 
         // do something 
     }); 
}]);

This way the $rootScope will always be $broadcasting down the scope hierarchy because - as the name suggests - it is the root scope. So now you don't have to worry about whether to use $emit or $broadcast because using the $scope means it will always be a child of $rootScope.


So in your case it's easy. The first controller should have $rootScope injected and use $broadcast. The second controller should have $scope and use $on, and look like this:

$scope.$on('onSomething', function(e) {
    $scope.getUserSettings();
});

Here is a working plunker: http://plnkr.co/edit/PrD3vB80lFSt0a9WQLJ9?p=preview

1
On

To achive this you don't really need to use $rootScope(but you can), $broadcast will call watchers for event in current and all child scopes, so this code in parent controller:

$scope.setData = function() {
    $timeout(function() {
      $scope.$broadcast("onSomething", "");
    }, 5000); 
  };

will trigger all $scope.$on('onSomething', ..) callback in current and all child controllers.

here's a codepin with working example(text 'event received' will appear after 5s in rendered html).

http://codepen.io/anon/pen/VYeEOg

0
On

In ionic, a controller function can't be called before the controller view load. If the view of your second controller has been loaded, you can do this:

secondview.html:

set ion-content id to get the controller scope

<ion-view title="second">
    <ion-content id="secondView">

    </ion-content>
</ion-view>

Seccond controller:

app.controller('SecondController', function($scope, $http) {

    $scope.someFunction = function(args) {
        alert(args.Message);
    };

});

Code:

app.controller('CodeController', function($scope) {

    $scope.$on('$ionicView.beforeEnter', function(){
        angular.element($('#secondView')).scope().someFunction({ Message: "Hello!" });
    });

});

Hope this helps.