9

If you have two area's on a page, i.e

<div ng-controller="LeftController">

</div>

<div ng-controller="RightController">

</div>

And lets say the LeftController can live and exist without the RightController. But should the RightController exist and something change ... then the LeftController needs to know about that change.

How can the LeftController know subscribe to those changes? Does that require a framework like Amplify or is this something that can be handled in Angular?

Usecase

So the problem I'm solving is theres some tabs on the screen. The user may or may not have access to either tabs.

When the tab is loaded initially, it loads from the server.

Tab 2 (RightController) may load before Tab 1 (LeftController), if Tab 1 doesn't exist or isn't loaded yet, and Tab 2 publishes a change. Nothing happens. If Tab 1 is loaded, user goes to Tab 2, changes a value, that may affect the UI in Tab 1. So Tab 2 publishes that hes changed. Tab 1 now changes what he needs based on the new information.

Phill
  • 18,398
  • 7
  • 62
  • 102
  • You can use $rootScope service `$broadcast` method to communicate across such controllers. This can act as pub\sub mechanism. – Chandermani Oct 22 '13 at 10:20
  • See this fiddle: http://jsfiddle.net/DotDotDot/f733J/ – subZero Oct 22 '13 at 10:22
  • In your scenario, if `LeftController` is not on the page, and `RightController` publishes. Does `LeftController` need notification of the event when it is then loaded? In other words, do you need durable pub/sub? Or just pub/sub to all currently listening subscribers? – Davin Tryon Oct 22 '13 at 10:22
  • @davin nope. Its purely there for elemental reasons. If the user goes and enables widget with Left controller. Then it would render the information that was published when it comes from the server. Then would subscribe to changes now that it exists. Basically I don't want to go to the server to check for changes. – Phill Oct 22 '13 at 10:32

2 Answers2

15

The is two ways to do this:

  1. Using events (emit or broadcast in the scope)
  2. Using a Service / Factory

I've made a plunker with these 2 options. I hope it help you.

Plunker - Example

Sources:

http://docs.angularjs.org/api/ng.$rootScope.Scope http://docs.angularjs.org/guide/dev_guide.services.creating_services

Deividi Cavarzan
  • 10,034
  • 13
  • 66
  • 80
6

You can create a simple service and inject it to both controllers.

app.factory('myService', function() {
    var onMessageCallbacks = [];
    var onMessage = function(cb) {
        onMessageCallbacks.push(cb);
    };

    var newMessage = function(msg){
        for (var cb in onMessageCallbacks) {
            onMessageCallbacks[cb](msg);
        }
    };

    return {
        onMessage: onMessage,
        newMessage: newMessage
    };
});

First, you use onMessage to subscribe to events:

app.controller('LeftController',
    function LeftController($scope, myService) {
        myService.onMessage(function(receivedMsg){
            // do sth...
        });
    }
);

When one of the controllers wants to say something, use newMessage:

app.controller('RightController',
    function RightController($scope, myService) {
        myService.newMessage('Hello!');
    }
);
idmean
  • 14,540
  • 9
  • 54
  • 83
lort
  • 1,458
  • 12
  • 16
  • 2
    Why not use `$broadcast` and `$emit`? – Davin Tryon Oct 22 '13 at 10:29
  • 1
    Surely using `$broadcast` is much more simple and seems prettier. Advantage of this solution comes if you want to manipulate the passed data inbetween (ie. implementing some logic that controllers shouldn't be aware of). – lort Oct 22 '13 at 10:38