0

I have a ng-repeat where i am checking a if condition and at the end of each repeation of loop i am setting a variable to a value from ng-repeat

Here is my variable which i want to set inside the ng-repeat

$scope.prvSid = "";

Here is my ng-repeat code

<ul class="chats" ng-repeat="chatData in chatboxData">
    <li ng-class="{ 'out': chatData.sender_id == user_id , 'in': chatData.sender_id != user_id }">
         {{   prvSid }}
         {{   chatData.sender_id }}
        <span ng-if=" prvSid != chatData.sender_id ">
            <img class="avatar" alt="" src="{{ url('default/img/user_default_logo.jpg') }}" />
        </span>
        <div class="message">
            <span class="body"> {{ chatData.message }} </span>
        </div>
        <span ng-init="prvSid = chatData.sender_id"></span>
        {{   prvSid }}
    </li>
</ul>

The problem which i am facing here is that whenever i print these values inside the ng-repeat then prvSid and chatData.sender_id is printing the same id the value of chatData.sender_id even for the first iteration and that's why this

<span ng-if=" prvSid != chatData.sender_id ">

condition is not working and my image is not displaying because for the first iteration the condition should be true because prvSid is "" and chatData.sender_id has some id in it

The purpose of this is to Henry Zou the purpose is to not show profile picture for two or more messages submitted by same user (if the sender_id is same)Then dont display the profile image.When the new message comes from another sender which means sender_id is different then show the profile image

at first the prvSid will be null so it will show the image because condition will not match at the end of each iteration i will set the prvSid to the current iteration sender_id to match this prv_id with sender_id in the next iteration

i am also getting messages after two seconds and then i am adding the new records in the chatboxdata if they dont exist in it

$scope.getlasttwosecMsgs = function(user_id_chat,chat_id,user,chatboxData,is_new) {
      $http.get(url+'/getlasttwosecMsgs/'+chat_id).success(function(data){
        angular.forEach(data, function(value, key) {
          var exists = $scope.containsObject(value,chatboxData);
          if (!exists) {
            $scope.chatboxData.push(value);
            console.log($scope.chatboxData);
          };
        });
      });
    }
$scope.containsObject = function(obj, list) {
        var i;
        for (i = 0; i < list.length; i++) {
            if (angular.equals(list[i], obj)) {
                return true;
            }
        }

        return false;
    };

1 Answers1

2

This new code snippet will check current userID against a list of users in the chatbox. For all users that's not the current user, show content.

approach #1 (preferred)

angular
  .module('app', [])
  .controller('myCtrl', function(){
  var vm = this;
  var prvSid = null;
  vm.chatboxData = [{id:1},{id:1},{id:2},{id:3}];
  
  vm.chatboxData.forEach(function(chatbox){
    if(prvSid !== chatbox.id){
      chatbox.showIcon = true;
    }
    prvSid = chatbox.id;
   });
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>

<div ng-app="app">
  <div ng-controller="myCtrl as vm">
    <ul class="chats" ng-repeat="chatData in vm.chatboxData">
      <li>
        <span ng-if="chatData.showIcon ">
            ICON
        </span>
        {{::chatData.id}}

      </li>
    </ul>
  </div>
</div>

approach #2

angular
  .module('app', [])
  .controller('myCtrl', function(){
  var vm = this;
  vm.prvSid = null;
  vm.chatboxData = [{id:1},{id:1},{id:2},{id:3}];
  
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>

<div ng-app="app">
  <div ng-controller="myCtrl as vm">
    <ul class="chats" ng-repeat="chatData in vm.chatboxData">
      <li>
        <span ng-if="chatData.showIcon ">
            ICON
        </span>
        {{::vm.prvSid}} {{::chatData.id}}
        <span ng-init="chatData.showIcon = (vm.prvSid !== chatData.id)"></span>
        <span ng-init=" vm.prvSid = chatData.id"></span>

      </li>
    </ul>
  </div>
</div>

approach #3 (without using controllerAs syntax)

angular
  .module('app', [])
  .controller('myCtrl', function($scope){
  var prvSid = null;
  $scope.chatboxData = [{id:1},{id:1},{id:2},{id:3}];
  
  $scope.chatboxData.forEach(function(chatbox){
    if(prvSid !== chatbox.id){
      chatbox.showIcon = true;
    }
    prvSid = chatbox.id;
   });
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>

<div ng-app="app">
  <div ng-controller="myCtrl">
    <ul class="chats" ng-repeat="chatData in chatboxData">
      <li>
        <span ng-if="chatData.showIcon ">
            ICON
        </span>
        {{::chatData.id}}

      </li>
    </ul>
  </div>
</div>

OLD ANSWER

In the video AngularJS MTV Meetup: Best Practices (2012/12/11), Miško explains "..if you use ng-model there has to be a dot somewhere. If you don't have a dot, you're doing it wrong.."

ng-repeat creates an inherited scope (think javascript prototype) for each item.

This code below will create $scope.prvSid for each item in the array and the value will always be chatData.sender_id.

<span ng-init="prvSid = chatData.sender_id"></span>

If you meant it to only have 1 instances of prvSid id, then what you'll need to do is initialize prvSid variable at the parent scope first (or use the dot(.) rule)

<div ng-init="prvSid = null"> <!-- initializing prvSid id @ parent scope -->
<ul class="chats" ng-repeat="chatData in chatboxData">
    <li ng-class="{ 'out': chatData.sender_id == user_id , 'in': chatData.sender_id != user_id }">
         {{   prvSid }}
         {{   chatData.sender_id }}
        <span ng-if=" prvSid != chatData.sender_id ">
            <img class="avatar" alt="" src="{{ url('default/img/user_default_logo.jpg') }}" />
        </span>
        <div class="message">
            <span class="body"> {{ chatData.message }} </span>
        </div>
<!-- this will now update the parent scope's prvSid instead of creating a new one for each item in the array -->
        <span ng-init="prvSid = chatData.sender_id"></span>
        {{   prvSid }}
    </li>
</ul>
</div>
Community
  • 1
  • 1
Henry Zou
  • 1,809
  • 1
  • 14
  • 19
  • can you please kindly tell me what is meant by or use the dot(.) rule. mean while let me try above solution Thanks for your answer to – Muhammad Usama Mashkoor Jan 12 '16 at 13:57
  • i have follow your instruction and update my code with your code
    and implemented the following solution but i am still facing the same issue
    – Muhammad Usama Mashkoor Jan 12 '16 at 14:06
  • the condition is not working the same problem kindly please help me on this it will be really appreciated – Muhammad Usama Mashkoor Jan 12 '16 at 14:14
  • 1
    the problem is that these variables are "live". When prvSid gets updated. You are always evaluating the last (stable) value in ngif. Can you explain a bit more about what prvSid is overall what this is suppose to do? – Henry Zou Jan 12 '16 at 14:18
  • @ Henry Zou the purpose is to not show profile picture for two or more messages submitted by same user (if the sender_id is same)Then dont display the profile image.When the new message comes from another sender which means sender_id is different then show the profile image – Muhammad Usama Mashkoor Jan 12 '16 at 14:22
  • at first the prvSid will be null so it will show the image because condition will not match at the end of each iteration i will set the prvSid to the current iteration sender_id to match this prv_id with sender_id in the next iteration – Muhammad Usama Mashkoor Jan 12 '16 at 14:23
  • 1
    I've created a simplified working snippet. It will only show user icon for the first message for that user. it uses controllerAs syntax (to add the dot). and moved code to the controller instead of using ng-init. – Henry Zou Jan 12 '16 at 14:35
  • added an alternative approach – Henry Zou Jan 12 '16 at 14:42
  • can you please kindly tell me why you have added the vm and why we are using lodash.js – Muhammad Usama Mashkoor Jan 12 '16 at 14:44
  • 1
    by using the "[controllerAs syntax](https://toddmotto.com/digging-into-angulars-controller-as-syntax/)", provides the .(dot) notations (see link above). Which is the best practice to avoid issues with child scope creating their own variables. Lodash is not used here. forEach is a built-in javascript function for looping through an array. The reference was just code snippet I use for every code sample. It's not used by the actual code. – Henry Zou Jan 12 '16 at 14:46
  • can not we do this in the simple angualr js because i will have to change my whole code if i use this approach dot(.) – Muhammad Usama Mashkoor Jan 12 '16 at 14:52
  • See approach #3 for code sample without dot syntax. Just keep in mind that it'll come back and bite you in the ass. – Henry Zou Jan 12 '16 at 15:04
  • sorry for the late reply can you please kindly tell me what we are using chatbox $scope.chatboxData.forEach(function(chatbox){ in this function and why we are using chatbox.id prvSid = chatbox.id; – Muhammad Usama Mashkoor Jan 12 '16 at 16:31
  • 1
    for each loop will update each item with "showIcon" to indicate whether or not the icon show be shown. and the prvSid = chatbox.id does the same as your original code . just keep in mine the code example i have is simplified, it doesn't use the same vars names/objects as yours. – Henry Zou Jan 12 '16 at 16:33
  • Thanks so i will pass chatboxData instead of chatbox in this function $scope.chatboxData.forEach(function(chatbox){ – Muhammad Usama Mashkoor Jan 12 '16 at 16:39
  • i am using your 2nd approach it working but i am having a problem with this approach in checking if object exists in the chatboxData array because i am fetching messages after 2 seconds.using ajax request and checking if the new index exists in the array or not but it again adding the records which already in the chatboxdata i have added code in my question please check it – Muhammad Usama Mashkoor Jan 12 '16 at 18:05
  • kindly please help me on this – Muhammad Usama Mashkoor Jan 12 '16 at 18:08
  • What error are you getting? and what's the problem? – Henry Zou Jan 12 '16 at 18:11
  • i am not getting error it is adding the same object two or three times when i get the last two seconds records and check for if the new object exists in the array or not if not then add it other wise dont add it – Muhammad Usama Mashkoor Jan 12 '16 at 18:16
  • the problem i am facing is that it is showing the newly added message two and three times and if i remove your coding it shows message only one time like it supposed to – Muhammad Usama Mashkoor Jan 12 '16 at 18:17
  • the containsObject function was working fine before your code but i remove your code it's again working fine – Muhammad Usama Mashkoor Jan 12 '16 at 18:20
  • you need to put a break point there in the code and debug that to see when the new message are added. – Henry Zou Jan 12 '16 at 18:26
  • i have added console.log('new') if (!exists) { in this condition where we are checking if the object exists in the array or not then it two show new in the console two time when the getlasttwosecMsgs request runs two time and more shocking thing is that the new message is showing on the screen three times – Muhammad Usama Mashkoor Jan 12 '16 at 18:39
  • @ Henry Zou if you have any other method to put break point and debug code then please kindly tell me so that i can explore the problem deeply – Muhammad Usama Mashkoor Jan 12 '16 at 18:40
  • add a debugger statement to your javascript: "debugger"; SEE: [chrome](https://developers.google.com/web/tools/chrome-devtools/?hl=en) [firefox](https://developer.mozilla.org/en-US/docs/Tools/Debugger) – Henry Zou Jan 12 '16 at 18:41
  • it is newly added code if i comment the code of second approach from ng-repeat then it shows only one message if i dont comment it then it add;s three messages can you please help me out on this – Muhammad Usama Mashkoor Jan 12 '16 at 19:34
  • Can't help you further without working code. Please create a project here and share the link http://jsbin.com – Henry Zou Jan 12 '16 at 19:36
  • if you dont mind can you please give me your skype id so that we can continue their i will take only 2 mins of your time so that i can show you the project or you we can do a teamviewer please kindly help me on this – Muhammad Usama Mashkoor Jan 12 '16 at 19:45
  • if this is for work, you should ask 1 of your senior developers to help you out. – Henry Zou Jan 12 '16 at 19:49
  • Actually i dont have any senior developers i am doing coding alone and please kindly help me on this it will be really help full to me as i dont know any other person whom i can approach for help. My skype is usama.mashkoor kindly please add me Thanks in advance it is for my own learning purpose to sir kindly please bear with me on this – Muhammad Usama Mashkoor Jan 12 '16 at 19:52
  • I have explored the object it is adding one extra field in this showIcon: i think due to this extra filed it is adding the multiple records in the chat – Muhammad Usama Mashkoor Jan 12 '16 at 20:01
  • in that case, simply compare the obj without showIcon. I am using a lodash method omit (look it up). if (angular.equals(list[i], _.omit(obj, 'showIcon'))) { return true; } – Henry Zou Jan 12 '16 at 20:05
  • Do these messages have IDs? If so, compare the IDs – Henry Zou Jan 12 '16 at 20:05
  • yes they have id's in that case, simply compare the obj without showIcon.can you please explain it more i have containsObject for this in the question to – Muhammad Usama Mashkoor Jan 12 '16 at 20:11
  • see my previous comment. _.omit(obj, 'showIcon') will return a new object without showIcon property. – Henry Zou Jan 12 '16 at 20:12
  • it is removing the showIcon from the object but it is still showing 3 messages in the chat box – Muhammad Usama Mashkoor Jan 12 '16 at 20:17
  • sorry, I can't help you anymore without working prototype. Create a working prototype on jsbin/plnkr/fiddler or even here @ stackoverflow. – Henry Zou Jan 12 '16 at 20:22