Search code examples
javascriptangularjsionic-frameworkeventsangularjs-scope

Ionic-AngularJS: Emitting Event To Parent Only ReBroadcasts To Child That Emitted Event


This may all sound a bit vague, but I am still learning and trying to understand how this works.

I started working with a 'side menu' starter ionic project, and it came already setup with a urlrouter config with an 'app' abstract state/view/controller and some additional states with their own controllers.

.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider

  .state('app', {
    url: "/app",
    abstract: true,
    templateUrl: "templates/menu.html",
    controller: 'AppCtrl'
  })


  .state('app.home', {
    url: "/home",
    views: {
      'menuContent': {
        templateUrl: "templates/home.html",
        controller: 'HomeCtrl'
      }
    }
  })

  .state('app.page2', {
    url: "/page2",
    views: {
      'menuContent': {
        templateUrl: "templates/page2.html",
        controller: 'Page2Ctrl'
      }
    }
  });
  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/app/home');
})

In the App Controller (AppCtrl), I am listening for an event called repeatMyEvent, and it broadcasts an event called myEvent.

I have a listener in each of the other controllers for the myEvent event. When I emit the repeatMyEvent event from either of the other controllers (I have a button on the template that calls the testEmit() function), I am only seeing the controller that emitted the repeatMyEvent event respond to the myEvent event. It also seems that maybe it is only the controller whose view is currently visible is responding to it. However, I am expecting all controllers to respond to it.

angular.module('starter.controllers', [])

.controller('AppCtrl', function($scope, $ionicModal, $timeout) {
  // Form data for the login modal


  $scope.$on('repeatMyEvent', function(event, args) {
    console.log('repeatMyEvent event received');


    $scope.$broadcast('myEvent');

  });



})

.controller('HomeCtrl', function($scope, $stateParams) {


  $scope.$on('myEvent', function(event, args) {
    console.log('HomeCtrl received myEvent');


  });

  $scope.testEmit = function() {
    $scope.$emit('repeatMyEvent');
  }


})

.controller('Page2Ctrl', function($scope, $stateParams) {


    $scope.$on('myEvent', function(event, args) {
        console.log('Page2Ctrl received myEvent');


    });

    $scope.testEmit = function() {
        $scope.$emit('repeatMyEvent');
    }


})

;

The only way I can make sense of this is that the controller for the abstract state isn't a singleton, and each of my controllers has their own version of it. Or have I completely misunderstood how $scope is supposed to work in relation to controllers?

And a follow up to all of that is how do I get this to work so that all controllers respond to broadcast messages from AppCtrl.

NOTE: I've also tried $scope.$root and I get the same behaviour.


Solution

  • I wasn't able to solve the specific communication problem because, as @Wawy pointed out in a comment on my original post,

    The way your state config is setup, there will only be one controller active at the same time. Since you are replacing the view with new content every time the page changes.

    So to handle my specific issue (which was to get one controller to tell another controller to refresh its data), I just reorganized my code to have the data refresh function placed in AppCtrl, and then each of the other controllers can just emit an event to tell it to execute the data refresh.