2

I'm creating an app where I have two apps or Divs. One is bootstrapped using ng-app directive, while the other one, I'm manually bootstrap using angular.bootstrap method.

The thing is both these divs are using a session service which $broadcasts to $rootScope, but as you can see when you the $rootScope is not shared between apps.

So a $rootScope.$broadcast in appB is not caught by appA.

Here is a demo:

angular.module('ngApp', [])
  .controller('ngAppController', function($scope, $rootScope) {
    $scope.msg = "Waiting for message..";
    $scope.$on('YO', function() {
      $scope.msg = 'Message recd';
    });

    //$rootScope.$broadcast('YO');
  });


var bElement = document.querySelector('#appB');
angular.module('appB', [])
  .run(function($rootScope) {
    $rootScope.msg = "Hello from app 'b'";
    $rootScope.$broadcast('YO');
  });
angular.bootstrap(bElement, ['appB']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="ngApp" ng-controller="ngAppController">
  <div>{{msg}}</div>
</div>
<div id="appB">
  <div>{{msg}}</div>
</div>

How can I make it so that I can catch broadcast from appB into appA?

6
  • why not just create one instance of application on common parent element of these two divs? Commented May 14, 2015 at 14:02
  • I'm using a template in which the header template is fixed (checks user status). The body part is another template that is loaded with PHP and it contains it's own app. But the session service is common between two and since the header already loads the data in session, I want to share the two. Commented May 14, 2015 at 14:08
  • window.postMessage with addActionListenerswould help you.. Commented May 14, 2015 at 14:15
  • You might find this question and answer useful. It works by maintaining an array of $rootScopes on the window and notifying each when a change occurs in the service. I'm using a pattern like this for my most recent project, and it seems to work well. Commented May 14, 2015 at 14:38
  • would it make sense to keep a gobal array of $rootScopes inside the service and then send broadcast to each $rootScope individually? Commented May 14, 2015 at 15:49

4 Answers 4

1

I'm pretty sure angular apps are not supposed to be aware of other angular apps on the page, so for this unusual case I would suggest building a "glue" application visible to both, e.g. window.superAngularScope = {...}. You could create whatever api you require in this object. However, unless you have a really good reason for violating encapsulation between the two angular apps, I'd advise you to find a different solution.

Sign up to request clarification or add additional context in comments.

Comments

0

I think in your case, you might need to use events outside of the angular framework, as separate angular modules don't share their rootScope.

You can use the window or document element to create event listeners and custom events, or use jQuery's trigger and on.

Comments

0

I would suggest you to use window.addEventListener with window.postMessage which do communication between two windows or on same window.

Code

angular.module('ngApp', [])
  .controller('ngAppController', function($scope, $rootScope, $window) {
    $scope.msg = "Waiting for message..";
    $scope.$on('YO', function() {
    //  $scope.msg = 'Message recd';
    //});
    $window.addEventListener('message', function(e) {
      $scope.$apply(function(){
        $scope.msg = e.data;
      });
    });
    //$rootScope.$broadcast('YO');
  });

var bElement = document.querySelector('#appB');
angular.module('appB', [])
  .run(function($rootScope, $window) {
    $rootScope.msg = "Hello from app 'b'";
    //$rootScope.$broadcast('YO');
    $window.postMessage('YO', '*');
  });
angular.element(document).ready(function() {
  angular.bootstrap(document, ['ngApp']);
  angular.bootstrap(bElement, ['appB']);
});

Working Plunkr

3 Comments

thanks for the solution but a lot of application are already written and are using the $scope.$on code. Using the message api will require me to change a lot of code everywhere... i'm thinking it would be better to keep a global array of $rootScope in the session service and then send individual broadcast to each each one of them (haven't tested it yet)
are you sure the solution you made is work for you?? I doubt that.
hi, yes it is working.. i've posted a working demo of it below.. I basically needed the session service to broadcast to all $rootScopes and it is doing it now.
0

After some trial and error, and based on the replies I got here, this is working for me:

(function() {
  var m = angular.module('session', []);
  var serviceInstance = null;
  var rootScopeArray = [];

  m.provider('$session', function() {
    this.$get = ['$q', '$http', '$timeout',  '$window', '$rootScope',
      function($q, $http, $timeout, $window, $rootScope) {
        rootScopeArray.push($rootScope);

        if (serviceInstance) {
          return serviceInstance;
        }

        $timeout(function(){
          for (var i = 0; i < rootScopeArray.length; i++) {
            rootScopeArray[i].$broadcast("YO");
          }
        }, 2000);
        
        return serviceInstance;
      }
    ];
  });

  return m;
})();

angular.module('ngApp', ['session'])
  .controller('ngAppController', function($scope, $session) {
    $scope.msg = "Waiting for message..";
    $scope.$on('YO', function() {
      $scope.msg = 'Message recd';
    });

    //$rootScope.$broadcast('YO');
  });


var bElement = document.querySelector('#appB');
angular.module('appB', ['session'])
  .run(function($rootScope, $session) {
    $rootScope.msg = "Hello from app 'b'";
    $rootScope.$on('YO', function() {
      $rootScope.msg = 'Message recd';
    });
  });
angular.bootstrap(bElement, ['appB']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ngApp" ng-controller="ngAppController">
    <div>{{msg}}</div>
  </div>
  <div id="appB">
    <div>{{msg}}</div>
  </div>

The solution seems to be working for my app and I didn't have to change any code. Just update the session service.

If there is a better way to do it, please do advise.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.