14
votes

I have an AngularJS app with the following controller. It worked fine with GET on regular JSON resource and manual request for updates, but I cannot make it work with Server-Sent Events. The problem I am facing is that after I receive an SSE event and set/update openListingsReport variable my view is not getting updated. I am obviously missing a very basic concept. Please help me fix this.

var rpCtrl = angular.module('rpCtrl', ['rpSvc']);

rpCtrl.controller('rpOpenListingsCtrl', ['$scope', 'rpOpenListingsSvc',
    function ($scope, rpOpenListingsSvc) {
        $scope.updating = false;

        if (typeof(EventSource) !== "undefined") {
            // Yes! Server-sent events support!
            var source = new EventSource('/listings/events');

            source.onmessage = function (event) {
                $scope.openListingsReport = event.data;
                $scope.$apply();
                console.log($scope.openListingsReport);
            };
        }
    } else {
        // Sorry! No server-sent events support..
        alert('SSE not supported by browser.');
    }

    $scope.update = function () {
        $scope.updateTime = Date.now();
        $scope.updating = true;
        rpOpenListingsSvc.update();
    }

    $scope.reset = function () {
        $scope.updating = false;
    }
}]);
2
Is EventSource tied to some kind of web socket (signalr, etc)? You can't just put scope functions on an angular controller and expect the server to send requests to it automatically.Fourth
EventSource is part of HTML SSE spec: developer.mozilla.org/en-US/docs/Web/API/EventSource Server is not the problem. I have updated value of openListingsReport in the client JS. I just cannot make AngularJS to show the updated value of openListingsReport in HTML.krl
Is the output of console.log($scope.openListingsReport) undefined or null or just blank? Try attaching the message event like this: source.addEventListener('message', function(e) { console.log(e.data); }, false); I found this article helpful: html5rocks.com/en/tutorials/eventsource/basicsTrazeK
I see, sorry. Try placing your $scope declaration inside the $apply(): $scope.$apply(function(){ $scope.openListingsReport = event.data;}); Check this out: smartjava.org/content/…TrazeK
Note that you rarely need to invoke $scope.$apply(); Dirty checking should handle the vast majority of cases, including this oneMawg says reinstate Monica

2 Answers

8
votes

The problem was in the following line:

$scope.openListingsReport = event.data;

which should be:

$scope.openListingsReport = JSON.parse(event.data);
-1
votes

Just a suggestion in case someone is using SSE with AngularJs.

If you want to use server side events ,I will suggest to use $interval service that is builtin within AngularJS instead SSE.

Below is the basic example.

<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>

<div ng-app="myApp" ng-controller="myCtrl">

    <p>Randome no:</p>

    <h1>{{myWelcome}}</h1>

</div>

<p>The $interval service runs a function every specified millisecond.</p>

<script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function ($scope, $interval, $http) {
        $scope.myWelcome = new Date().toLocaleTimeString();
        $interval(function () {
            $scope.myWelcome = $http.get("test1.php").then(function (response) {
                $scope.myWelcome = response.data;
            });
        }, 3000);
    });
</script>

</body>
</html>

test1.php

<?php

echo rand(0,100000);