Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call controller function from service in angularjs

I am using socket.io to enable chat in my app and i am using a service SocketService to perform all the socket stuff. When a message came then i want to trigger a function of a controller from the service SocketService to make some changes in the UI. So i want to know that how can i access the function of a controller from the service. Sample Code:

.service('SocketService', function ($http,$rootScope,$q) {
  this.connect = function(){
    var socket = io();
    socket.on('connect',function(){
      // Call a function named 'someFunction' in controller 'ChatController'
    });
  }
});

This is the sample code for service.

Now the code for controller

.controller('ChatController',function('SocketService',$scope){
  $scope.someFunction = function(){
     // Some Code Here
  }
});
like image 335
Vinit Chouhan Avatar asked Mar 05 '15 17:03

Vinit Chouhan


2 Answers

You could achieve this by using angular events $broadcast or $emit.

In your case $broadcast would be helpful, You need to broadcast your event in $rootscope that can be listen by all the child scopes which has $on with same event name.

CODE

.service('SocketService', function($http, $rootScope, $q) {
    this.connect = function() {
        var socket = io();
        socket.on('connect', function() {
            // Call a function named 'someFunction' in controller 'ChatController'
            $rootScope.$broadcast('eventFired', {
                data: 'something'
            });
        });
    }
});


.controller('ChatController', function('SocketService', $scope) {
    $scope.someFunction = function() {
        // Some Code Here
    }
    $scope.$on('eventFired', function(event, data) {
        $scope.someFunction();
    })
});

Hope this could help you, Thanks.

like image 119
Pankaj Parkar Avatar answered Oct 17 '22 06:10

Pankaj Parkar


I know this is an old question, but I have another option. I have a personal bias against $broadcast - it just doesn't feel very 'angularish', I prefer making explicit calls in my code.

So instead of broadcasting to the controller and triggering another digest cycle, I prefer to have the controller register itself to the service, as below. Just be careful not to introduce any circular dependencies if the controller makes use of the same service. This works best with the controllerAs syntax, so that the calling service does not need to care about $scope.

Yes, this is more code than $broadcast, but it does give the service total access to the entire controller - all of it's methods and properties.

.service('SocketService', function ($http,$rootScope,$q) {
  var _this = this;    
  this.chatController = null;
  this.registerCtrlr = function (ctrlr) {
    _this.chatController = ctrlr;
  };
  this.unRegisterCtrlr = function () {
    _this.chatController = null;
  };

  this.connect = function(){
    var socket = io();
    socket.on('connect',function(){
      // Call chatController.someFunction if chatController exists
      if (_this.chatController) {
        _this.chatController.someFunction();
      }
    });
  };
});

.controller('ChatController',['SocketService', '$scope', function(SocketService, $scope){
  SocketService.registerCtrlr(this);
  //-- make sure controller unregisters itself when destroyed - need $scope for this
  $scope.$on('$destroy', function () {
    SocketService.unRegisterCtrlr();
  });
  this.someFunction = function(){
    // Some Code Here
  }
}]);
like image 2
grumpyhoser Avatar answered Oct 17 '22 05:10

grumpyhoser