11

Ich benutze socket.io, um Chat in meiner App zu aktivieren, und ich verwende einen Service SocketService, um alle Socket Zeug durchzuführen. Wenn eine Nachricht kam, möchte ich eine Funktion eines Controllers vom Dienst SocketService auslösen, um einige Änderungen in der Benutzeroberfläche vorzunehmen. Also ich möchte wissen, wie kann ich auf die Funktion eines Controllers aus dem Dienst zugreifen. Beispielcode:Call-Controller-Funktion aus Service in angularjs

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

Dies ist der Beispielcode für den Dienst.

Jetzt ist der Code für die Steuerung

.controller('ChatController',function('SocketService',$scope){ 
    $scope.someFunction = function(){ 
    // Some Code Here 
    } 
}); 
+0

[http://stackoverflow.com/questions/20621028/angularjs-calling-a-controller-function-from-a-service][1] [1]: http: //stackoverflow.com/questions/20621028/angularjs-calling-a-controller-funktion-from-a-service – TechnoCrat

Antwort

29

Sie können dies erreichen, indem Winkel Ereignisse $broadcast oder $emit verwenden.

In Ihrem Fall $broadcast wäre hilfreich, Sie Ihre Veranstaltung in $rootscope auszustrahlen, die von allen untergeordneten Bereiche werden hören, die $on mit demselben Ereignis Namen hat.

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 Sie, Dank helfen.

+0

Dank @pankajparkar $ Broadcast hat hier perfekt funktioniert. –

+0

@VinitChouhan cool, froh, Ihnen zu helfen, Danke :) Happy Coding –

+1

@PankajParkar: Die perfekte Lösung für mein Problem. In meinem Fall waren die Controller nicht verschachtelt und ich musste das Update an den anderen senden. Es ist genau wie Ramban Ilaaj. –

1

Ich weiß, das ist eine alte Frage, aber ich habe eine andere Option. Ich habe eine persönliche Voreingenommenheit gegenüber $ Broadcast - es fühlt sich einfach nicht sehr "eckig" an, ich bevorzuge explizite Aufrufe in meinem Code.

Anstatt also zum Controller zu senden und einen anderen Digest-Zyklus auszulösen, möchte ich lieber, dass der Controller sich selbst beim Dienst anmeldet, wie unten. Seien Sie vorsichtig, keine zirkulären Abhängigkeiten einzuführen, wenn der Controller den gleichen Dienst verwendet. Dies funktioniert am besten mit der controllerAs-Syntax, so dass der aufrufende Dienst sich nicht um $ scope kümmern muss.

Ja, das ist mehr Code als $ Broadcast, aber es gibt dem Dienst insgesamt Zugriff auf den gesamten Controller - alle Methoden und Eigenschaften.

.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 
    } 
}]); 
+0

Warum den ganzen Controller hinzufügen? Abonnieren Sie einfach die spezifische Funktion. Denken Sie daran, dass, wenn innerhalb der Funktion $ scope (oder vm) geändert wird, die Änderung der Ansicht mit [$ scope.apply als Wrapper] gemeldet wird (http://jimhoskins.com/2012/12/17/angularjs-and -apply.html) –

+0

Gute Punkte, mit ein paar Vorbehalten: a) Wenn Sie die spezifische Funktion registrieren, achten Sie darauf, den Controller anzugeben, an den es gebunden ist - 'SocketService.registerCtrlrFn (this.someFunction.bind (this)', and b) Wenn die Dienstlogik immer als Teil eines Digest-Zyklus ausgeführt wird, ist der Wrapper $ scope.apply nicht erforderlich. Wenn die Service-Logik nicht Teil eines Digest-Zyklus ist, wie in der ursprünglichen Frage, ist es notwendig. Wenn es sich möglicherweise in einem Digest-Zyklus befindet oder nicht, verwenden Sie stattdessen einen $ timeout-Wrapper. – grumpyhoser

+0

Weitere Informationen zu [$ scope.gilt vs $ timeout] (http://stackoverflow.com/questions/23070822/angular-scope-apply-vs-timeout-as-a-safe-apply) – grumpyhoser