I have an object that is updated dynamically and populates the DOM using ng-repeat. However the DOM is not updating in the realtime, once a new value is pushed into the object even though a console.log
shows that the value is added.
//appView.html
<div class="row">
<uib-tabset type="pills" vertical="true">
<uib-tab ng-repeat="(key, value) in channelMap">
<uib-tab-heading>
<span>{{value.displayName}}</span>
</uib-tab-heading>
<div class="messageWrapper">
<div class="thread" ng-repeat="threads in value.messageThreads track by $index">
<span>{{threads.text}}</span>
</div>
<div class="message-area">
<input type="text" ng-model="messageText">
<button ng-click="sendMessage(key,value,messageText)">Send</button>
</div>
</div>
</uib-tab>
</uib-tabset>
</div>
//Controller.js
$scope.channelMap = {};
subscriptionCallback = function(data)
{
var messageFromServer = JSON.parse(data.body);
if (messageFromServer.isSuccess) {
var messageObj = messageFromServer.data;
console.log(messageObj);
if (messageObj.messageType === "CREATE_CHANNEL") {
// Subscribing to private channel
subscribeToChannel(messageObj.text, subscriptionCallback);
//Put it in channelsMap with reciever id as key
var threadObj = {};
var displayName = "";
if($scope.user.id == messageObj.recieverId){
displayName = messageObj.senderName + " (" + messageObj.usernameSender + " )";
}
else{
displayName = messageObj.recieverName + " (" + messageObj.usernameReciever + " )";
}
threadObj.displayName = displayName;
threadObj.channenId = messageObj.text;
threadObj.messageThreads = [];
$scope.channelMap[messageObj.recieverId] = threadObj;
console.log($scope.channelMap);
}
else{
var msg = {};
msg.text = messageObj.text;
msg.senderId = messageObj.senderId;
msg.recieverId = messageObj.recieverId;
$scope.channelMap[messageObj.recieverId].messageThreads.push(msg);
console.log($scope.channelMap[messageObj.recieverId].messageThreads);
}
}
}
The function subscriptionCallback
is called once a response is received from server and is responsible for populating data in $scope.channelMap which it does successfully if I examine console.log
, however if I perform any action on DOM, the DOM is updated.
I also tried to use controller as . (dot) syntax, however it rendered the ng-repeat part blank even after I perform any action on DOM.
To judge from your comment
Subscription callback is called once the server sent a message to client, this snippet is a part of web socket based program
As the subscriptionCallback is called from outside of angular control, any changes to the controller scope will not be synced to the view as angular don't know when changes have been made.
To solve this, wrapp your scope changes in $scope.$apply(fn)
;
$scope.channelMap = {};
subscriptionCallback = function(data)
{
$scope.$apply(function() {
var messageFromServer = JSON.parse(data.body);
if (messageFromServer.isSuccess) {
var messageObj = messageFromServer.data;
console.log(messageObj);
if (messageObj.messageType === "CREATE_CHANNEL") {
// Subscribing to private channel
subscribeToChannel(messageObj.text, subscriptionCallback);
//Put it in channelsMap with reciever id as key
var threadObj = {};
var displayName = "";
if($scope.user.id == messageObj.recieverId){
displayName = messageObj.senderName + " (" + messageObj.usernameSender + " )";
}
else{
displayName = messageObj.recieverName + " (" + messageObj.usernameReciever + " )";
}
threadObj.displayName = displayName;
threadObj.channenId = messageObj.text;
threadObj.messageThreads = [];
$scope.channelMap[messageObj.recieverId] = threadObj;
console.log($scope.channelMap);
}
else{
var msg = {};
msg.text = messageObj.text;
msg.senderId = messageObj.senderId;
msg.recieverId = messageObj.recieverId;
$scope.channelMap[messageObj.recieverId].messageThreads.push(msg);
console.log($scope.channelMap[messageObj.recieverId].messageThreads);
}
}
});
}