Update list after push AngularJS

8

I have a list with several data ( $scope.messages ), but only some data interest me. After loading this list I make a foreach and get only the data that interest me and give push to a new list. This way:

angular.forEach($scope.messages, function(msgBD) {
     if((msgBD.user == $scope.usuario   && msgBD.destino == destino) || (msgBD.user == destino && msgBD.destino == $scope.usuario )){
          $scope.msgs.push(msgBD);
     }
});
     $scope.messages = $scope.msgs;

However in the view my ng-repeat does not update itself

  <ul class="media-list" ng-repeat="message in messages track by $index">
  {{message.text}}
  </ul>

When I use $scope.$apply before the push works perfectly:

  $scope.$apply(function(){
          $scope.msgs.push(msgBD);
   });

But of this error in the console:

  

"Error: [$ rootScope: inprog]    link $ rootScope / inprog? p0 =% 24apply

Is there any way to solve this problem? Or treat this error?

UPDATE I created a Fiddle to better exemplify my problem.

  • Open two browsers between two different names and login
  • Click the user that is online (The user you created in the other browser)
  • Send a message
  • Nothing happens, then click the same user you sent message and you will see that the message is updated.
  • This is the problem The message in the list only "Updates" when I click again on the user I sent the message to.

    Fiddle : link

    Update 2

    Chat example working perfectly after solution presented by @oOAkiraOo link

    NOTE: If many users are online, just click clear users.

        
    asked by anonymous 19.11.2015 / 20:09

    5 answers

    5

    Problem with syncronism.

    I solved it this way:

    $scope.novaMensagem = function(message) {
        message.user = $scope.usuarioLogado.login;
        message.destino = $scope.target;
        Message.create(message).then(function(ref) {
            console.log('--> ', ref);
            //$scope.mensagemPara($scope.target); //Não precisa com a inclusão do $watch
        });
        $scope.newmessage.text= "";
        //$scope.newmessage = "";
    };
    

    UPDATE 1.0 :  And to leave instantaneous, I added the code below in the controller chatCtrl :

     Message.all.$watch(function(evnt) { 
            //console.log(evnt);
            var msgs = [];
            $scope.usuario = $scope.usuarioLogado.login;
            angular.forEach(Message.all, function(msgBD) {
                if ((msgBD.user == $scope.usuario && msgBD.destino == $scope.target) || (msgBD.user == $scope.target && msgBD.destino == $scope.usuario)) {
                    msgs.push(msgBD);
                }
            });
            $scope.messages = msgs;
        });
    
        
    23.11.2015 / 19:35
    3

    Oops, try using $scope.$digest() to update your bindings and watchers

        
    20.11.2015 / 16:29
    2

    One option is to use the filter in the list, instead of processing it and displaying it modified.

    Similar to this answer , you can do the following:

    <ul class="media-list" ng-repeat="message in messages track by $index | filter:{user: usuario, destino: destino}">
      {{message.text}}
    </ul>
    
        
    20.11.2015 / 11:38
    2

    Your problem involves some situations.

    First:

    The message attribute is not starting correctly. When you start the Message.all method it returns undefined or undefined. The correct one would be: $ scope.message = Message.all || [];

    Second:

    Some json attributes of both the message and the users have undefined attributes. This is because you are using the $ scope.userLogic.login , the correct one would be $ scope.userLogic , because you do not have the login attribute set. The angle does not work with undefined values. Be careful!

    Third:

    Be careful when assigning values to an angular array. When using $ scope.array = otherArray, you kill the binding of the element with the angular DOM. Instead use Arrays.copyOf var b = Arrays.copyOf (a, a.length); . That way the angular will not lose your DOM gift relationship. This item generates your main problem, the array update does not reflect in the DOM.

        
    23.11.2015 / 19:34
    2

    Your problem can not be solved in the way you want it to be, since you are involving some variables that are independent of the message list.

    The list is stored on the client, that is, only on the client's computer. From the moment he uploaded that list, he can not 'guess' whether or not there was a change in the database in order to 'reload' the new data.

    In order for you to identify that a message list (or any other table) has changed in the database, you need a socket service that will do exactly what you need:

    • A user sends (inserts) a new message;
    • The message is saved in the database;
    • The database sends a notification to the socket service (initialized on all clients);
    • The socket notifies all logged-in users that there has been a change in that list;
    • Yes, the list is loaded with the new messages;

    The socket service will vary depending on your backend, but check out this site: socket.io can help you search for what you need to.

        
    23.11.2015 / 19:51