2

I have fallowing setup for my project:

  • mainApp main angular module, containing EventBus factory
  • app1 first module with mainApp injected
  • app2 second module with mainApp injected

app1 and app2 are two modules placed on the same page, both have mainApp injected.

I am trying to communicate between app1 and app2 using EventBus factory, which is defined in mainApp. Unfortunately, I can't get it to work (app1 doesn't catch app2 event, and opposite).

How should I resolve that? Have I take a wrong approach?

EventBus.subscribe("App1Ctr.event", function (event, data) {
    console.log("App2handler");
    $scope.name = data.newVal;
});


$scope.fireEvent = function () {
    EventBus.broadcast("App2Ctr.event", {"newVal": "App2Ctr"});
};

Here is a plnkr

Kamila
  • 371
  • 5
  • 13
  • 1
    Can you please add a little bit detail something like: 1) What is your expected output/behavior? 2) What is current output/behavior? – Khalid Hussain May 10 '16 at 08:29
  • @KhalidHussain expected output: I have several modules and want all of them to listen for events send from one main(injected) module. current output - no events caught neither in app1 nor app2 – Kamila May 10 '16 at 08:41
  • Can you please just add a `console.log` in your plnkr and print current output? – Khalid Hussain May 10 '16 at 08:44
  • updated this plunker https://plnkr.co/edit/ZpdmdOvHve3y0OsF2nON?p=preview it looks like broadcast is fired up correctly but subscription doesn't work. – Kamila May 10 '16 at 08:51
  • Just a little bit more info, specify a `console log` where current output is wrong and mention your expected output. It will be better if you [edit] all the information into your question. – Khalid Hussain May 10 '16 at 09:14
  • the problem is the EvenBus.subscribe handler is not run after event is broadcasted, so there is no output. – Kamila May 10 '16 at 09:17

2 Answers2

0

You need to change the way dependencies are injected. Your main.js needs to contain this:

var mainApp = angular.module("mainApp", ["app1", "app2"])

Your two app1.js and app2.js can drop the dependency requirement from mainApp:

var app1 = angular.module("app1", [])

and

var app2 = angular.module("app2", [])

Your initialization code in index.html becomes

<script>
    angular.element(document).ready(function() {
        angular.bootstrap(document, ["mainApp"]);
    });
</script>

You will need to change the references to {{name}}, too, so that they include a dot (because of the whole prototypical inheritance thing in angular). See this plunkr, and this question for more details on $broadcast, $emit, $on, and $rootScope.

Community
  • 1
  • 1
michele b
  • 1,825
  • 2
  • 20
  • 26
  • unfortunatelly, I can't do this, as this would up-side-down the project structure. – Kamila May 10 '16 at 08:58
  • your `main.js` currently only contains a factory for `EventBus`, so you might as well rename it to `eventBus.js`. The alternative is to make your `app1` and `app2` children of a common parent, use `$scope.$emit` on the children, and have that parent re-broadcast events down the hierarchy using `$scope.$broadcast`, like it's shown in [this answer](http://stackoverflow.com/a/31358365/1159164) – michele b May 10 '16 at 09:07
  • The example works with different controllers, but how do I nest angular apps/modules? – Kamila May 10 '16 at 09:11
  • I've edited [this plunkr](https://plnkr.co/edit/8wrFmOtRCBFIAhjykgUe?p=preview) to show you the standard way of dealing with multi-module angular apps (replacing the manual bootstrap part with `ng-app`). That's just how you usually define the modules of your app, you list them as dependencies for your main module. – michele b May 10 '16 at 09:42
  • Thnks, but as I said, I can't do this that way, The project is really big and containing many angular apps, I can't revert the structure of all project now, as it will break lot of other functionality. Thanks anyway. – Kamila May 10 '16 at 10:11
0

I managed to find a solution. The broadcast method in EventBus should look something like:

_broadcast = function(eventName, data) {
    console.log("EventBus broadcast: " + eventName);
    angular.element(document.getElementById('app1')).scope().$root.$emit(eventName, data);
  };

Since it has to get angular app by ID, I will use in addition EventDispatcher to handle this.

Kamila
  • 371
  • 5
  • 13