13

I am playing with Angular and SignalR, I have tried to create a service which will act as a manager.

dashboard.factory('notificationsHub', function ($scope) {
  var connection;
  var proxy;

  var initialize = function () {
    connection = $.hubConnection();
    proxy = connection.createHubProxy('notification');

    proxy.on('numberOfIncidents', function (numOfIncident) {
      console.log(numOfIncident);
      $scope.$emit('numberOfIncidents', numOfIncident);
    });

    connection.start()
      .done(function() {
        console.log('Connected');
      })
     .fail(function() { console.log('Failed to connect Connected'); });
  };

  return {
    initialize: initialize
  };
});

however I get the error Error: Unknown provider: $scopeProvider <- $scope <- notificationsHub.

How can I use pubsub to pass all the notifications to the controllers? jQuery maybe?

georgeawg
  • 48,608
  • 13
  • 72
  • 95
li-raz
  • 1,678
  • 2
  • 29
  • 57
  • You could just drop by and check out my lastest push on the github: [angualr-signalr](https://github.com/roylee0704/angular-signalr). It basically supports whatever it has from the original Signalr js client and I have added a killer functionality which it enables to propagate events properly into the Angular's scope system. – Roy Lee May 30 '15 at 18:00
  • How to write jasmine unit test cases for this? – Karthik Feb 01 '16 at 11:38

4 Answers4

5

$scope does not exist in this context as that's something injected when a controller is created and a new child scope is made. However, $rootScope is available at the time you need.

Also, be aware $emit() goes upward and your controller scopes wont see it. You would either need to switch to $broadcast() so the event goes downwards or inject $rootScope as well to the controllers you want to be able to subscribe to 'numberOfIncidents'

Check out the angular docs and a useful wiki on scopes.

johlrich
  • 1,771
  • 1
  • 12
  • 11
  • For a SignalR application in particular I recommend the `$emit` + `$rootScope.$on` path for reasons described well here: http://stackoverflow.com/a/19498009/288703 – johlrich Nov 18 '13 at 20:57
3

Here is a great example showing how to wrap the proxy in a service and use $rootScope for event pub/sub.

http://sravi-kiran.blogspot.com/2013/09/ABetterWayOfUsingAspNetSignalRWithAngularJs.html

Jason Capriotti
  • 1,836
  • 2
  • 17
  • 33
  • 1
    I'd avoid this example to be honest. He's using a service which only has half the logic; the other half (the `$on` subscriber) is baked into his controller. – GFoley83 Jul 22 '14 at 07:25
  • 1
    Good point that the highlight of the example is wrapping of the proxy. But wouldn't subscribers be anywhere they are needed? In this example of updating a property on $scope, where should the logic go? – Jason Capriotti Aug 05 '14 at 13:43
1

As already noted in johlrich's answer, $scope is not avaliable inside proxy.on. However, just switching to $rootScope will most likely not work. The reason for this is because the event handlers regisrered with proxy.on are called by code outside the angular framework, and thus angular will not detect changes to variables. The same applies to $rootScope.$on event handlers that are triggered by events broadcasted from the SignalR event handlers. See https://docs.angularjs.org/error/$rootScope/inprog for some more details.

Thus you want to call $rootScope.$apply() from the SignalR event handler, either explicitly

proxy.on('numberOfIncidents', function (numOfIncident) {
  console.log(numOfIncident);
  $scope.$apply(function () {
    $rootScope.$emit('numberOfIncidents', numOfIncident);
  });
});

or possibly implicitly through $timeout

proxy.on('numberOfIncidents', function (numOfIncident) {
  console.log(numOfIncident);
  $timeout(function () {
    $rootScope.$emit('numberOfIncidents', numOfIncident);
  }, 0);
});
Community
  • 1
  • 1
hlovdal
  • 26,565
  • 10
  • 94
  • 165
0

I tried to use $apply() after changing value, i tried to use $apply(functuin() {value = 3}), and also i tried to use $emit and $broadcast for changing value and it doesn't help. But i found solution we need in html after in controller you can use

var scope2 = angular.element("#test").scope();
    scope2.point.WarmData.push(result);
    $scope.$apply();

P.s. I understand that it is very old question, but may by smb, as i, need this solution.