2

I have a simple question: what's the best ('cleanest', 'scaleable') path one should go when it comes to interact between (let's say) two controllers. Would that be to define a service and watch that service's return-value in order to react?

I setup a simple example here, where I watch the service's current value:

$scope.$watch(
    function() {
        return myService.getValue();
    },
    function(newVal) {
        $scope.value1 = newVal;
    });

and update that service's value when one of the buttons is clicked.

Can this be done better, smaller, cleaner somehow? What's the best practice here?

Cheers.

2 Answers 2

3

Use service to share data between controllers

Your case is trying to share data between controllers, rather than watch service's value in controllers, I think directly reference service object to controller's scope is a better way

So your view can be

 <pre ng-controller="cntrl1">Value in cntrl1: {{ myService.value }} <button ng-click="update('value1')">Change to 'value1'</button></pre>

  <pre ng-controller="cntrl2">Value in cntrl2: {{ myService.value }} <button ng-click="update('value2')">Change to 'value2'</button></pre>

and change your controllers to

app.controller('cntrl1', function(myService, $scope) {
  $scope.myService = myService;
  $scope.update = function(str) {
    $scope.myService.setValue(str);
  }
});

app.controller('cntrl2', function(myService, $scope) {
  $scope.myService = myService;
  $scope.update = function(str) {
    $scope.myService.setValue(str);
  }
});

Use $broadcast/$emit

Just as @squiroid points out, you can use $broadcast to broadcast events to any controllers who is monitoring targeted events.

Please note here, you'd better not use $rootScope.$broadcast + $scope.$on but rather $rootScope.$emit+ $rootScope.$onas $broadcast event will bubble down through all descendant scopes, which might lead to serious performance problems.

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

3 Comments

D'oh - so easy, but yet so nice! Thanks man. Can the $scope.update = function() { ... } be avoided to be duplicated, somehow?
Regarding envolving the rootscope, that'd work, thanks for that. Is subscribing for the service not a "cleaner" approach, rather than going to the rootscope to do these kind of things?
Instead of using $scope.update = function (), you can directly use ng-click="myService.value = 'value1'" which is straight forward and avoid redundant code. Personally I prefer subscribing to service instead of broadcasting on rootScopes. Angular service is singleton and can be passed as reference, so simply inject service into controller is a natural JavaScript way of thinking.
1

This is the best way to communicate b/w the controller sharing same data via sevice but it is limited b/w controllers having the same service:-

Instead you can also choose to broadcast events that are captured by other controllers and change that data accordingly this way is more scaleable but not clean :-)

Sender ctrl :-
$rootScope.$broadcast('update', 'Some data'); //method that lets pretty much everything hear it even $scope too.

or

$rootScope.$emit('update', 'Some data');// only lets other $rootScope listeners catch it 

Listen Ctrl :-

   $rootScope.$on('update', function (event, data) {
        console.log(data); // 'Some data'
      });

2 Comments

This solution is simpler but $broadcast event would go down through all descendant scopes, right? $emit might be better.
Yes ,In case of performance emit will work better if you are only listen rootScope.Thanks :-)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.