Reputation: 2992
I am writing an AngularJS client application which communicates with SignalR 2.2. The Angular application also uses Angular UI Router library.
My hub class looks like:
MessagingHub.cs
public class MessagingHub : Hub
{
public void Connect()
{
Clients.Caller.connected();
}
}
The main app module is given below:
app.js
(function () {
'use strict';
angular.module('app', ['ui.router']);
//Global error handler for the signalR
$.connection.hub.error(function (err) {
console.log('An error occurred: ' + err);
})
//Make signalR proxy as a service available to other components.
angular.module('app').value('message', $.connection.messagingHub);
angular.module('app').config(function ($stateProvider, $urlRouterProvider) {
// For any unmatched url, send to /contact
$urlRouterProvider.otherwise("/contact");
$stateProvider
.state('contact', {
url: "/contact",
templateUrl: "/app/contact.html"
})
.state('messaging', {
url: "/messaging",
templateUrl: "/app/messaging.html"
})
.state('about', {
url: "/about",
templateUrl: "/app/about.html"
});
});
})();
contact.html and about.html files contain nothing apart from some headings.
messaging.html is given below:
messaging.html
<div ng-controller="messaging as vm">
<h1>Messaging</h1>
<div ng-show="vm.isConnected"><p class="label label-primary">Welcome...</p></div>
<div ng-show="vm.isAvailable"><p class="label label-info">Your status is available now</p></div>
<br />
<br />
<button class="btn btn-sm btn-primary" ng-click="vm.onStartMessaging()">Connect</button>
</div>
and the corresponding controller is given below:
messaging.js
(function () {
'use strict';
angular
.module('app')
.controller('messaging', ['$scope', '$timeout','message', messaging]);
function messaging($scope, $timeout, message) {
var vm = this;
vm.isConnected = false;
vm.isAvailable = false;
vm.onStartMessaging = onStartMessaging;
message.client.connected = onConnected;
function onStartMessaging() {
$.connection.hub.logging = true;
$.connection.hub.start().done(function () {
message.server.connect();
$timeout(function () {
vm.isConnected = true;
});
});
}
function onConnected() {
vm.isAvailable = true;
$scope.$apply();
}
}
})();
when I first go to "Messaging" view and click 'Connect' button, it calls the Connect
function on the Hub
which then calls connected
function on the caller. The handler function in my Angular controller sets vm.isAvailable = true
which in turn shows a lebel on the view.
Everything works fine but when I move to other view and come back and click the 'Connect' button again, same process goes through as mentioned above but in the onConnected()
javascript function the value of vm.isAvailable
is already set to true
so the label is not displayed at all which is odd.
Can anybody help me to understand why this is happening and what options do I have.
Upvotes: 0
Views: 245
Reputation: 2992
I found the solution for this problem. The only thing I had to do was to handle the state change event for the ui router and close the connection with SignalR hub like below:
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
$.connection.hub.stop();
});
Now it really makes sense to close the hub connection when the user navigates away from the messaging view but why the vm.isAvailable
is not set to false
on revisiting the view if the SignalR hub connection was not closed when the user navigated away is still a mystery for me. If someone knows the answer to this and can give me some logical reason I will accept the answer.
Upvotes: 2