I am fetching data from websocket in a factory. Every time a message arrives I update it.
In my controller I have bound the same inside the $scope. However when the websocket message comes, UI doesn't get updated.
After doing a lot of search I figured out that I need to call $scope.$apply if I need to update the UI (if changes are not saved by using any angular method).
I set up a timer using setInterval to call $scope.$apply every second. But it is a hack. I would like to remove this. Is there a way to tell angular to refresh from inside the factory, without using this hack?
Factory:
app.factory('StocksFactory', function() {
...
factory.stocksCurrentPrices = {};
// Subscribe to the websocket for stock prices
const stocksSocket = new WebSocket('ws://...');
stocksSocket.onmessage = function(event) {
// Adding to current prices
factory.stocksCurrentPrices[..] = ...;
};
return factory;
});
Controller:
app.controller('StocksController', function($scope, StocksFactory) {
$scope.stocks = StocksFactory.stocksCurrentPrices;
// HACK This is used to force the digest every second as the changes in $scope.stocks
// was not reflected in the UI
setInterval(function() {
$scope.$apply();
}, 1000);
});
You can not use $scope
in an AngularJS service, since services do not belong to any scope, but they are singlenton through the application.
But you CAN inject the $rootScope
into the service and notify through the entire application, like this:
app.factory('StocksFactory', function($rootScope, $timeout) {
...
factory.stocksCurrentPrices = {};
// Subscribe to the websocket for stock prices
const stocksSocket = new WebSocket('ws://...');
stocksSocket.onmessage = function(event) {
// Adding to current prices
factory.stocksCurrentPrices[..] = ...;
// notify of changes
$timeout(function() {
$rootScope.$apply();
})
};
return factory;
});
Notice that:
$rootScope.$apply();
inside a $timeout
in order to Prevent error $digest already in progress $rootScope.$broadcast