Piuma
Piuma

Reputation: 1

Change ng-show in another controller?

I want to change ng-show in another controller than ng-show is.

myApp.controller('popupCtrl', function() {});

myApp.controller('changePopup', function($rootScope){
  // now i wanna show my Ppopup
  $rootScope.popup = true;
});
<div ng-controller="popupCtrl">
  <div ng-show="popup">
    Popuptext
  </div>
</div>

But this doesn't work... How can I fix it? Thanks!

Upvotes: 0

Views: 1081

Answers (3)

Simon H
Simon H

Reputation: 21005

Here is a working demo for you - sorry I changed the controller names, but I am sure you will be able to build on this. Good luck

angular.module('myApp', [])
  .controller('c1', function($scope) {
    // now i wanna show my Ppopup
    $scope.popup = false;
    $scope.$on('popup', function() {
      $scope.popup = true;
    });

  })
  .controller('changepopup', function($rootScope, $scope) {
    // now i wanna show my Ppopup
    $scope.clicker = function() {
      $rootScope.$broadcast('popup')
    }
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="c1">
    <div ng-show="popup">
      Popuptext
    </div>
  </div>

  <button ng-controller="changepopup" ng-click="clicker()">Click me</button>
</div>

Upvotes: 0

Ashkan Hovold
Ashkan Hovold

Reputation: 908

One way to solve this is to use $rootScope.$broadcast

Here is an example: http://plnkr.co/edit/EmJnZvXFRWv6vjKF7QCd

var myApp = angular.module('myApp', []);


myApp.controller('popupCtrl', ['$rootScope', '$scope', function($rootScope,$scope) {

 $scope.popup = false;

 $rootScope.$on('changePopup', function(event, data) {
  $scope.popup = !$scope.popup;
});


}]);

myApp.controller('changePopup', ['$rootScope', '$scope', function($rootScope, $scope) {

$scope.changePopup = function() {
$rootScope.$broadcast('changePopup', 'data could be sent here');
}
}]);

View:

<div ng-controller="popupCtrl">
<div ng-show="popup">
  Popuptext
</div>

<div ng-controller="changePopup">
<button ng-click="changePopup()">Change the popup</button>
</div>

Using a service/factory is a better solution for cross controller communication if you are working on a large application, but for a smaller app I would say using $broadcast, $emit and $on is sufficient.

Upvotes: 0

Callum Linington
Callum Linington

Reputation: 14417

So first thing, you should never add to the $rootScope or change it in anyway. It has been optimised by the angular team.

Second thing, there is no need to involve the $rootScope.

Here is a demo showing how to communicate across two controllers.

The key is the event aggregator pattern:

Communicator.register(function (newValue) {
    vm.value = Communicator.value;
});

I created a function in the Communicator to register a callback function. The aim is that when a value gets changed the callback function is fired off. I.e. an event is triggered (change event).

The second key part is fire that change event off:

Communicator.change(!Communicator.value);

Here we pass through to the change function a new value which will do two things:

  1. Update the internal value so we can keep track of it
  2. Loop through all the registered callbacks and execute them passing in the new value.

By implementing this pattern, we can minimise the extent to which we communicate around our application ($rootScope can have a tendency to traverse the scope heirarchy when you $broadcast).

Now we can follow more closely the principle of single responsibility. Our class is aptly named in its current scope, when we look at this factory we can tell it is supposed to "communicate".

Finally, with a global event aggregator pattern ($rootScope) it is far more difficult to keep track of where these events are being broadcast from, and where they'll end up. Here we don't have that issue

Upvotes: 3

Related Questions