0

From what I've read, it seems using $rootScope.$broadcast is not advisable unless absolutely necessary. I'm using it in a service to notify a controller that a variable has changed. Is this incorrect? Is there a better way to do it? Should I be using watch instead (even though the variable only changes on user interaction) ?

the service:

function Buildservice($rootScope) {
        var vm = this;
        vm.box= [];

    var service = {
        addItem: addItem,

    };
    return service;

    // Add item to the box
   // Called from a directive controller
    function addItem(item) {
        vm.box.push(item);
        broadcastUpdate();
    }

    function broadcastUpdate() {
        $rootScope.$broadcast('updateMe');
    }

// In the controller to be notified:

    // Listener for box updates
    $scope.$on('updateMe', function() {
        // update variable binded to this controller
    });

// and from a separate directive controller:

function directiveController($scope, buildservice) {

    function addToBox(item){
        buildservice.addItem(item);
    }

So this works just fine for me, but I can't figure out if this is the way I should be doing it. Appreciate the help!

shanahobo86
  • 467
  • 2
  • 7
  • 23
  • yes, its a correct implementation. from Service to controller use `$rootScope.$broadcast` – Maxim Shoustin Dec 15 '15 at 14:28
  • @Maxim Shoustin That's exactly what he / she is doing.. Except that the $broadcast is wrapped up in a function. The question, if I understand correctly, is if there's a better (as in best practice) way of doing this. – leroydev Dec 15 '15 at 14:29
  • I'm particularly curious to know, if using watch is a better approach. – shanahobo86 Dec 15 '15 at 14:35
  • You can achieve this kind of behavior without watch/broadcast by implementing an observer pattern in your service that notifies everybody who registered upon change of an internal var. I guess that would be slightly more efficient but perhaps a bit more work. – skubski Dec 15 '15 at 14:48
  • http://stackoverflow.com/questions/15800454/angularjs-the-correct-way-of-binding-to-a-service-properties – Eugene Dec 16 '15 at 10:29

2 Answers2

0

If you are in same module, why don't you use $scope instead of $rootScope?

Ibrahim Mumcu
  • 243
  • 2
  • 11
0

You can use a callback function to notify the controller something has changed. You supply the service a function from the controller, and invoke that particular function whenever your variable has been changed. You could also notify multiple controllers if needed.

I have created a small example:

HMTL:

<div ng-controller="CtrlA as A">
  {{A.label}}
  <input type="text" ng-model="A.input" />
  <button ng-click="A.set()">set</button>
</div>
<div ng-controller="CtrlB as B">
  {{B.label}}
  <input type="text" ng-model="B.input" />
  <button ng-click="B.set()">set</button>
</div>

JS

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

app.controller('CtrlA', function(AService) {
  var vm = this;
  vm.label = AService.get();

  vm.notify = function() {
    vm.label = AService.get();
  }

  vm.set = function() {
    AService.set(vm.input)
  }

  AService.register(vm.notify);
});

app.controller('CtrlB', function(AService) {
  var vm = this;
  vm.label = AService.get();

  vm.notify = function() {
    vm.label = AService.get();
  }

  vm.set = function() {
    AService.set(vm.input)
  }
  AService.register(vm.notify);
});



app.factory("AService", function() {

  var myVar = "Observer";
  var observers = [];

  return {
    get: function() {
      return myVar;
    },

    set: function(name) {
      console.log(name);
      myVar = name;
      this.notify();
    },

    register: function(fn) {
      observers.push(fn);
    },

    notify: function() {
      for( i = 0; i < observers.length; i++) { 
        observers[i]();
      }
    }
  }
})

You will see upon executing this that the controllers get notified when the internal variable has been changed. (Notice: I haven't filtered the original sender from the list) (Plnkr)

skubski
  • 1,586
  • 2
  • 19
  • 25
  • thanks so much for your reply. A callback is a nice solution, but is it a better solution? If so, why is it better than using $rootscope.$broadcast? Thanks – shanahobo86 Dec 15 '15 at 16:24
  • The event is not bubbled down the application but kept to the observers and listeners only. No checks on the digest cycle and no pollution of your $(root)scope. But it requires some more hacking on your keyboard. – skubski Dec 15 '15 at 21:01