Currently, I am experimenting with an Angular application that utilizes a websocket to interact with the backend. I've encountered some challenges in getting Angular's data binding to function correctly.
In this scenario, I have developed a service responsible for establishing the websocket connection. Whenever a message is received through the websocket, it is added to an array containing all incoming messages.
In my controller, I link this array of messages to the scope and then utilize ng-repeat
to display them on my view template.
Service:
factory('MyService', [function() {
var wsUrl = angular.element(document.querySelector('#ws-url')).val();
var ws = new WebSocket(wsUrl);
ws.onopen = function() {
console.log("connection established ...");
}
ws.onmessage = function(event) {
Service.messages.push(event.data);
}
var Service = {};
Service.messages = [];
return Service;
}]);
Controller:
controller('MyCtrl1', ['$scope', 'MyService', function($scope, MyService) {
$scope.messages = MyService.messages;
}])
Partial:
<ul>
<li ng-repeat="msg in messages">
{{msg}}
</li>
</ul>
However, this setup does not update as expected. Even though new messages are added to the array, the list displaying all messages fails to refresh. This issue puzzles me because of Angular's two-way data binding feature.
I did find a solution by invoking $rootScope.apply()
within the service when pushing a new message:
ws.onmessage = function(event) {
$rootScope.$apply(function() {
Service.messages.push(event.data);
});
}
My inquiries are:
Is it normal behavior in Angular for the list not to auto-update without using
$rootScope.apply()
?What necessitates the use of wrapping it in
$rootScope.apply()
?Is employing
$rootScope.apply()
the correct approach to remedying this situation?Are there better alternatives than
$rootScope.apply()
for addressing this concern?