SignalR does not update ng-view when changing pages

0

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

2.- I have a father controller and a son controller for the ng-view

3.- For the ng-view I have a template with a span linked to the property subCtrl.id and another span linked 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 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 via FIDDLER, the client receives it and the console print 'Angel eyes', however 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 the explanation are long, but in reality it is very simple, please see the following GIFS:

Works with the initial route:

It does not work after changing the route:

What am I doing wrong?

    
asked by Tuco 25.04.2016 в 17:09
source

2 answers

3

What I see happens is that the attach to the SignalR event is being received by the first controller, so the second one does not take the action.

You could move the definition of SignalR to the base controller who is in charge of receiving all the communication and this sends it to the controller son event

app.controller('mainCtrl', ['$location', function ($location) {
   var self = this;
   self.optionSelected = function (option) {
      $location.path("/" + option);
   };

    self.hub = $.connection.AppHub;


    self.hub.client.Hello = function () {
         console.log("Hello");
         $scope.$broadcast('UpdateName', 'Angel eyes');
         };

    $.connection.hub.start().done(function () {
        console.log('SignalR connection started');
    });

}]);

app.controller('subCtrl', ['$routeParams', '$scope', function ($routeParams, $scope) {
    var self = this;
    self.something= {};
    self.something.id = $routeParams.id;
    self.something.name = 'Blondie';

    $scope.$on('UpdateName', function(name) 
    { 
        self.something.name = name;
        $scope.$apply();
    });

}]);

As you will see I use the $broadcast and $on to communicate the controller

Understanding $ emit , $ broadcast and $ on in AngularJS

    
answered by 25.04.2016 / 19:31
source
0

Thanks Leandro, basically your answer with some adjustments:

In the mainCtrl use $ rootScope instead of $ scope and $ broadcast instead of $ emit:

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');
    });
}]);

In the client I receive the name of the method and the value, and update the view:

$scope.$on('UpdateName', function (name,value) {
    self.something.name = value;
    $rootScope.$apply();
});
    
answered by 25.04.2016 в 20:16