Update list after push Angularjs

Asked

Viewed 3,991 times

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 take only the data that interests me and give push in a new list. That 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;

But in the view mine ng-repeat does not update alone

  <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 give this console error:

"Error: [$rootScope:inprog] http://errors.angularjs.org/1.4.7/$rootScope/inprog? P0=%24apply

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


UPDATE I created a Fiddle to better exemplify my problem.

  1. Open two browsers between two different names and Login
  2. Click the user who is online(The user q you created in the other browser)
  3. Send a message
  4. Nothing happens, so click the same user you sent it to a message again and you will see that the message is updated.

That’s the problem the message the list only "Updates" when I click again on the user I sent the message.

Fiddle: http://jsfiddle.net/tjruzpmb/60/


Update 2

Example of the chat working perfectly after solution presented by @oOAkiraOo http://jsfiddle.net/sinkz/tjruzpmb/103/

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

  • What is this variable of yours "fate"?

  • Dude, another question, in which event are you trying to update your array? at the time of rendering the screen? in some textbox that is changed?

  • In the event that sends the message, I’m riding a fiddle

  • @Techies by chance you’re wearing this exhibit inside some ng-if or ng-show ? I remember that I once had a problem with this, the update only went into them with $apply(); but if used outside the if or show, it updates in real time, with no need for $apply() or $Digest().

  • @Techies from what I understand, you’re trying to create a chat, that’s it?

  • 1

    $scope.apply() makes asynchronous use of databind, calling the $scope.$digest(), its use is recommended in a few cases, usually used along with the $timeout or setTimeout(). For this reason, the event when it is called more than once, without time interval, gives this error. That is, it is slow.

Show 1 more comment

5 answers

5


Problem with syncronism.

I solved it that 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 for a moment, 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;
    });

3

Whoa, try to use $scope.$digest() to update your bindings and your Watchers

  • where do I put ? inside the foreach?

  • No no, put after all, after the $Scope.messages = $Scope.msgs;. It will update your bind and show the value on your screen. Let me know if it worked as you needed it later ;)

  • Another thing, you don’t need to create another array that is a property of your $Scope. Create a normal array: var msg = [];

  • I created a normal array and tried using $Digest. But you gave this error: "Error: [$rootScope:inprog] http://errors.angularjs.org/1.4.7/$rootScope/inprog? P0=%24apply

  • Put it in a codepen or a Fiddler for testing, please?

  • I’ll try to make

  • Here is fiddle: jsfiddle.net/tjruzpmb/60

  • Open two browsers, put different names and click login. Then click on the user and send a message

  • After you send a message you have to click on the user name again, only this way the list is updated

  • Every time you send a message click on the user name again

Show 5 more comments

2

Your problem involves some situations.

First:

The message attribute is not being started correctly. When you start Message.all returns Undefined or undefined. The correct would be: $Scope.message = Message.all || [];

According to:

Some json attributes of both message and users are with undefined attributes. This is because you are using the $Scope.usuarioLogado.login the correct would be $Scope.usersLog., because you do not have the login attribute defined. The angular does not work with undefined values. Be careful!

Third:

Be careful when assigning values to an angular array. Using $Scope.array = otherArray kills the element’s connection to the angular DOM. Instead use Arrays.copyOf var b = Arrays.copyOf(a, a.length);. This way the angular will not lose its relationship dom the DOM. This item generates your main problem, the update of the array does not reflect in the DOM.

2

Your problem cannot be solved in the way you intend, as you are involving some variables that are independent of the mailing list.

The list is stored on the client, that is, only on his computer. From the moment he loaded that list, he cannot 'guess' whether or not there was a change in the database to be able to 'reload' with the new data.

In order to identify that a mailing list (or any other table) has undergone a change in the database, you need a socket that will do just 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 in all clients);
  • The socket notifies all logged in users that there has been a change in that list;
  • Ai yes the loading of the list with the new messages;

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

  • Firebase works with Sockets, so I don’t have to mess with that part.

  • Yes, in this case, perfect.

2

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

Similar to that answer, Voce can do the following:

<ul class="media-list" ng-repeat="message in messages track by $index | filter:{user: usuario, destino: destino}">
  {{message.text}}
</ul>
  • Check this error: "Error: [filter:notarray] http://errors.angularjs.org/1.4.7/filter/notarray?p0=0

  • you initialized the arrays you are using?? var messages = [ ]

  • Yes: $scope.messages= Message.all;

  • The Array is initialized by pulling all existing data into the database

  • That mistake says: Expected array but received: 0 is because its variable is set to 0 instead of an array.... might be getting started late... (after the filter is applied)... try putting a $Scope.messages = [ ] right at the beginning of the module

  • I did what you said and it’s still the same, there’s no way to do it in the controller?

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.