2

Can you advice me the right sole of some issue? I have next situation:

1.I load list of items from server and list it with ng-repeat in container here:

<div layout="column" id={{vm.folderId}}container flex layout-align="start center" class='container' dragula='"first-bag"'>
   <div id={{item.id}}child class="md-whiteframe-5dp capitalize itemsInList" layout="column"  ng-repeat="item in vm.workItems | filter:search">
      <div layout="column" flex >
         <div class="workItemName">{{vm.getWorkItemName(item.metadata)}}</div>
         <div class="workItemDescription">{{vm.getWorkItemDescription(item.metadata)}}</div>
      </div>
   </div>
</div>

So lets say we have listed next list:

item_1
item_2
item_3
item_4

than I drop another element into this container, ITEM_5. After I've droped server gives me new list: item_1 - item_2 - item_3 - item_4 - item_5 and I update my vm.workItems here:

if (data.ok) {
    if (data.content.items.length != vm.workItems.length) {
        vm.workItems = data.content.items; //from server
        SharedDataService.setLastUpdateTimeStamp(SharedDataService.getNewUpdateTimeStamp());
    }
}

After when it ng-repeat fresh items it also view droped element in list.So in the end I have:

item_1 //ng-repeated
item_2 //ng-repeated
item_3 //ng-repeated
item_4 //ng-repeated
item_5 //ng-repeated
item_5 //droped element

How to avoid this? is there some normal solving?

update. I drop element ,when it's droped I make request to server to ad new item to list:

  $scope.$on('first-bag.drop', function (e, el, container) {
        var elementId = parseInt(el[0].id);
        var newContainerId = parseInt(container[0].id);
        var newPrevElementId;
        var newPrevElement = document.getElementById(el[0].id).previousElementSibling;

        if(newPrevElement) {
            newPrevElementId = parseInt(newPrevElement.getAttribute('id'));
        } else  if(!newPrevElement)  {
            newPrevElementId = newContainerId;
        }

        if(exContainerId != newContainerId) {
            WebSocketService.addItem(elementId, exContainerId,
}
}
Serhiy
  • 1,893
  • 9
  • 30
  • 48
  • 1
    Found another similar question asked. [http://stackoverflow.com/a/24490995/5726639](http://stackoverflow.com/a/24490995/5726639). This might help you. [Angular-filter](https://github.com/a8m/angular-filter) – Nikita Ag Oct 10 '16 at 06:36

2 Answers2

1

You can do

ng-repeat="item in vm.workItems track by item.id | filter:search"

If each item has a unique ID(or something unique property), and if you use track by ID, then even if server returns previous items with a new item added to it DOM will not get re-rendered, only new item will be added to the DOM.

Plunker (take a look at console)

ng-repeat adds $$hashkey property to each object when it repeats through a list of objects.

When your server returns the new data, though there are already existing objects, since, the new data(each object) does not contain $$hashkey property in it, ng-repeat re-renders then thinking they are new objects.

If you use track by ID then ng-repeat does not add a $$hashkey property, it keeps track of each item using ID. So, even if server returns same data again, since, ID's matches, ng-repeat does not repeat them. If there are new ID's then it renders then to the DOM.

Take a look at this blog post.

Ravi Teja
  • 1,097
  • 8
  • 13
0

Try this in your function:

let data = data.content.items;
let temp = [];
data.forEach(function(item) {
    if (temp.indexOf(item) === -1) {
    temp.push(item);
  }
});
vm.workItems = temp;

Hope this helps.

DieuNQ
  • 975
  • 1
  • 7
  • 11
  • the same.It lists received items via ng-repeat before droped DOM element. but thank you for trying. – Serhiy Oct 07 '16 at 08:14