1.- It's a simple ng-route, I have 3 buttons, each button navigates to a new route.
2.- I have a parent controller and a child controller for theng-view
3.- For it ng-view
I have a template with a span bound to the property subCtrl.id
and another span bound to 'subCtrl.something'
with an initial value of something.id=1
andsomething.name='blondie'
4.-If I call the signalR method through Fiddler and I am in the initial route everything works fine: SignalR updates the view with 'Angel Eyes'
PROBLEM : BUT if I change the route and navigate to ctrl.optionSelected(2) or ctrl.optionSelected(3) and call the SignalR method through FIDDLER, the client receives it and the console prints 'Angel eyes', however the view it does not actualize!
HTML
<div ng-app="app">
<div ng-controller="mainCtrl as ctrl">
<button ng-click="ctrl.optionSelected(1)">1</button>
<button ng-click="ctrl.optionSelected(2)">2</button>
<button ng-click="ctrl.optionSelected(3)">3</button>
<div ng-view></div>
</div>
<script type="text/javascript" src="~/Scripts/jquery-2.2.3.min.js"></script>
<script type="text/javascript" src="~/Scripts/angular.min.js"></script>
<script type="text/javascript" src="~/Scripts/angular-animate.min.js"></script>
<script type="text/javascript" src="~/Scripts/angular-route.min.js"></script>
<script type="text/javascript" src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script type="text/javascript" src="~/signalr/hubs"></script>
<script type="text/javascript" src="~/Scripts/app.js"></script>
JAVA SCRIPT
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/:id', {
templateUrl: '/Templates/template.html',
controller: 'subCtrl',
controllerAs: 'sctrl'
});
}]);
app.controller('mainCtrl', ['$location', function ($location) {
var self = this;
self.optionSelected = function (option) {
$location.path("/" + option);
};
}]);
app.controller('subCtrl', ['$routeParams', '$scope', function ($routeParams, $scope) {
var self = this;
self.something= {};
self.something.id = $routeParams.id;
self.something.name = 'Blondie';
self.hub = $.connection.AppHub;
/*****HERE IS THE PROBLEM*************/
self.hub.client.Hello = function () {
console.log("Angel eyes");
self.something.name= 'Angel eyes';
$scope.$apply();
};
/*************************************/
$.connection.hub.start().done(function () {
console.log('SignalR connection started');
});
}]);
Templates/Template.html
<span ng-bind="sctrl.something.id"></span>
<span ng-bind="sctrl.something.name"></span>
SIGNAL R method:
[HttpGet]
[Route("api/app/GetSignalRTest")]
public IHttpActionResult GetSignalRTest()
{
var context = GlobalHost.ConnectionManager.GetHubContext<AppHub>();
context.Clients.All.hello();
return Ok();
}
The code and the explanation are long, but it's really very simple, please see the following GIFS:
It works with the initial route:
It doesn't work after changing the route:
What am I doing wrong?
What I see happening is that the attach to the event
SignalR
is being received by the first controller, that's why the second one doesn't take the action.You could move the SignalR definition to the base controller who is in charge of receiving all the communication and sends it through an event to the child controllers
As you can see, I use the
$broadcast
and$on
to communicate the controllersUnderstanding $emit, $broadcast and $on in AngularJS
Thanks Leandro, it's basically your answer with some adjustments:
In the mainCtrl use $rootScope instead of $scope and $broadcast instead of $emit:
On the client I receive the method name and value, and update the view: