13

In order to have two controllers speak to each other in Angular, it is recommended to create a common service which is made accessible to both controllers. I've attempted to illustrate this in a very simple fiddle. Depending on which button you press, the app is supposed to tailor the message below the buttons.

So why isn't this working? Am I missing something obvious or more fundamental?

HTML

<div ng-controller="ControllerOne">
  <button ng-click="setNumber(1)">One</button>
  <button ng-click="setNumber(2)">Two</button>
</div>
<div ng-controller="ControllerTwo">{{number}} was chosen!</div>

JavaScript

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

app.factory("Service", function () {
  var number = 1;
  function getNumber() {
    return number;
  }
  function setNumber(newNumber) {
    number = newNumber;
  }
  return {
    getNumber: getNumber,
    setNumber: setNumber,
  }
});

function ControllerOne($scope, Service) {
  $scope.setNumber = Service.setNumber;
}

function ControllerTwo($scope, Service) {
  $scope.number = Service.getNumber();
}
David Jones
  • 10,117
  • 28
  • 91
  • 139

3 Answers3

17

Try creating a watch in your controller:

$scope.$watch(function () { return Service.getNumber(); },
   function (value) {
       $scope.number = value;
   }
);

Here is a working fiddle http://jsfiddle.net/YFbC2/

Yoggi
  • 572
  • 4
  • 11
  • My question was actually a simplified version of my actual code, which is *much* more complex (too much to post on SO). In my complex setup, Peter's suggestion didn't fix my issue, although it may actually be the best solution for the specific question I posed (+1). Adding a watch was exactly what I needed though, so I'm selecting this as the correct answer (in my case). Thanks everyone! – David Jones Oct 18 '13 at 18:57
5

Seems like problem with property that holds a primitive value. So you can make these changes:

app.factory("Service", function () {
    var number = {val: 1};
     function getNumber() {
        return number;
    }
    function setNumber(newNumber) {
        number.val = newNumber;
    }
    return {
        getNumber: getNumber,
        setNumber: setNumber,
    }
});

See fiddle

Community
  • 1
  • 1
Peter Gerasimenko
  • 1,906
  • 15
  • 13
3

Just call in HTML Service.getNumber() and in controller ControllerTwo call Service like:

 $scope.Service = Service;

Example:

HTML

<div ng-controller="ControllerOne">
  <button ng-click="setNumber(1)">One</button>
  <button ng-click="setNumber(2)">Two</button>
</div>
<div ng-controller="ControllerTwo">{{Service.getNumber()}} was chosen!</div>  

JS

function ControllerOne($scope, Service) {    
    $scope.setNumber = Service.setNumber;  
}

function ControllerTwo($scope, Service) {
        $scope.Service = Service;
}

Demo Fidlle

Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225