I dont fancy Angular much, its slow and Knockout with its MVVM approach is much cleaner, and faster since computed and observables only mutate and change view state when they actually need to (That will change with Angular 2.0). Anyway, my current customer sports Angular and then you just have to form inline đŸ˜€ We needed immediate update and you know I love event aggregation and probably know that I have a library for it, you can read more about it here!
I created a little wrapper for the the vanilla javascript client, install it using nuget
Install-Package SignalR.EventAggregatorProxy.Client.Angular
Basically it works by extending the Angular $rootScope and adds a eventAggregator function to all scopes. The eventAggregator function resolves the scope and then creates a closure with two methods, subscribe and publish. You can now listen to a event like (Serverside or client side event).
$scope.eventAggregator().subscribe(MyApp.MyEvent, onEvent);
This works because we can digest the scope and that will update the UI
subscribe: function(type, handler, constraint) { signalR.eventAggregator.subscribe(type, function(e) { handler(e); if (scope.$$phase == null) { scope.$digest(); } }, scope, constraint); }
One cool feature with Angular is that it has built in lifetime to the scopes. This means the scopes will unsubscribe them self without any explicit code for it.
scope.$on('$destroy', function() { signalR.eventAggregator.unsubscribe(scope); });
You can also publish client side events like
$scope.eventAggregator().publish(new MyApp.ClientEvent("data"));
Full code of angular wrapper
angular.module("signalR.eventAggregator", []) .run([ "$rootScope", function($rootScope) { function createScope(scope) { scope.$on('$destroy', function() { signalR.eventAggregator.unsubscribe(scope); }); return { subscribe: function(type, handler, constraint) { signalR.eventAggregator.subscribe(type, function(e) { handler(e); if (scope.$$phase == null) { scope.$digest(); } }, scope, constraint); }, publish: function(event) { signalR.eventAggregator.publish(event); } } } $rootScope.eventAggregator = function() { return this.__eventAggregator = this.__eventAggregator || createScope(this); }; } ]);