Search code examples
javascriptangularjssignalrng-view

SignalR not updating ng-view after changing page


1.- It's a simple ng-route setup, I have 3 buttons, each button navigates to a new path.

2.- I have a parent controller and a child controller for ng-view

3.- For ng-view I have a template with a span bound to property subCtrl.id and another span bound to 'subCtrl.something' with an initial value of something.id=1 and something.name='blondie'

4.-If I call the signalR method through Fiddler and I'm at the intitial 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 SignalR method through FIDDLER, the client receives it and console prints 'Angel eyes', BUT the view is not updated!

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>

JAVASCRIPT

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 explanation seems to be too long but it's actually very simple, please watch the following gifs

Works with initial route:

enter image description here

Does not work after changing view:

enter image description here

What am I doing wrong here?


Solution

  • Thanks to Leandro Tutini who answered this on es.stackoverflow

    Only the first controller is being attached to the SignalR event that's why the second controller is not working.

    You can move the SignalR definition to the base controller which is going to catch the events and propagate them to the child controller

    app.controller('mainCtrl', ['$location', '$scope', '$rootScope', function ($location, $scope, $rootScope) {
    
    var self = this;
    self.optionSelected = function (option) {
        $location.path("/" + option);
    }
    self.hub = $.connection.AppHub;
    
    
    self.hub.client.Hello = function () {
    console.log("Hello");
    $rootScope.$broadcast('UpdateName', 'Angel eyes');
    };
    
    $.connection.hub.start().done(function () {
        console.log('SignalR connection started');
        });
    }]);
    
    
    app.controller('subCtrl', ['$routeParams', '$scope', function ($routeParams, $scope, $rootScope) {
    var self = this;
    self.something= {};
    self.something.id = $routeParams.id;
    self.something.name = 'Blondie';
    
    $scope.$on('UpdateName', function(name){ 
        self.something.name = name;
        $rootScope.$apply();
        });
    
    }]);