Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested ngFor and trackBy, comparsion of arrays

I have a bigger project there I have 4 nested *ngFor. So the creation is arround 200 lines long, I think sharing wouldn´t help so I explain it as good as I can. The problem is after refreshing the object, the elements get destroyed and recreated. Which leeds to a performance issue (Nothing I matter about just 0,5 seconds) and an scrolling back to the top. And this is my problem I dont want this happening.

The array:

 array[0-X] = For Paginator
 array[X][1-3] = contains 3 columns // #Column
 array[X][X][1-9] = divides the column in 9 blocks // #InfoBlock
 array[X][X][X][1-X] = the content of the single blocks // #Info

After the creation, the user is able to move only the #Info element over his settings wherever he want.

As example moving a #Info to a different #InfoBlock. Via subscription I save the change to the database and reload the whole array.

Like this:

this.pageinator = result;

Now it destryoys the divs and creates them new, this leads my layout to scroll to top. I tried trackby, but cause of the whole array is overwritten it won't work.

The question: Is there a way to comparison 2 arrays and just take the changes to the previous one. I know I could not reload the data, but this can cause problems because the software isn´t used by just 1 user.

Edit: An example

array[0][1][1][1] = "Content X"
array[0][1][2][2] =  undefined
// After reloading
array[0][1][1][1] =  undefined
array[0][1][2][2] =  "Content X"
// Now I want Angular to just change this 2 elements, cause the others stay the same. 

Edit 2: I have found out that sometimes:

this.pageinator = result;

Automaticly only take the changes. This happens in 1 out of 10 times.

like image 278
Doomenik Avatar asked Jul 14 '17 08:07

Doomenik


1 Answers

Since you control the event of leaf change inside the array, why not to switch values inside of array by position? You switch the values between array[0][1][1][1] and array[0][1][2][2] in the array and the *ngFor takes care of updating the view.

I dropped a simple plunkr here

Edit

If only the leafs change on your array and the elements of the main array remain on the same position, then you have an easy mission of comparing the elements by position and switch the elements as the leafs are different like:

//this assumes that main array won't change - same length and position
for (let i=0; i < originalArray.length; i++) {
  if (originalArray[i][leafindex] !== newArray[i][leafindex] {
    originalArray[i] = newArray[i];
  }
}

If the main array changes length or elements position, the implementation of comparison to look for the changes became difficult and prone to slow performance. In that case, I'll advise you to do it like you do now with rewriting the array, but take the scrollTop value before changing the data and apply the same scroll after the elements are re-rendered.

like image 51
BogdanC Avatar answered Oct 03 '22 11:10

BogdanC