1

Basically I need to keep an over-arching index for my double ngFor loop.

Example:

Header 1
item 1 - index = 0
item 2 - index = 1
item 3 - index = 2

Header 2 
item 1 - index = 3

Header 3 
item 1 - index = 4
item 2 - index = 5

I have tried using a custom directive then calling an increment function, however that seems to just be updating the class index too quickly. Look here: Call a function inside ngFor in angular2

Dave
  • 59
  • 7

1 Answers1

1

You can obtain the global index of each element by calling a method getIndex(i, j) which accepts the two loop indexes as arguments:

<div class="group" *ngFor="let group of data; let i = index">
  Header {{i + 1}}
  <div *ngFor="let item of group; let j = index">
    Item {{j + 1}} - index = {{ getIndex(i, j) }}
    </div>
</div>

and which uses Array.reduce() as follows:

data = [
  ["a", "b", "c"],
  ["p"],
  ["x", "y"],
];

getIndex(outerIndex, innerIndex) {
  return this.data.reduce((accumulator, currentGroup, groupIndex) => {
    return accumulator + (groupIndex < outerIndex ? currentGroup.length : 0);
  }, innerIndex);
}

See this stackblitz for a demo.


Here is an alternative version of getIndex(i, j) which uses a simple for loop:

getIndex(outerIndex, innerIndex) {
  let totalIndex = innerIndex;
  for (let groupIndex = 0; groupIndex < outerIndex; groupIndex++) {
    totalIndex += this.data[groupIndex].length;
  }
  return totalIndex;
}
ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
  • 1
    The `getIndex` method is called for all items on each Angular detection cycle (but it should not loop "infinitely"). To avoid that, you would have to save the calculated indexes. You could make each item an object with an `index` property, and manage the refresh of these saved indexes. – ConnorsFan Apr 09 '19 at 19:42
  • To be honest don't quite get what you mean. So this method will be called on all items in the Cycle. So if my data array is length 10, it will be called 10 times? For the fix, I'm having trouble understanding. – Dave Apr 09 '19 at 20:48
  • Every time the view is refreshed, the method is called for each item (in the example given in the question, it is called 6 times). And the Angular detection cycle is triggered in various conditions. Does the `getIndex` method cause performance issues in your application? In addition to my previous suggestion, there are other ways to optimize the code (see [this article](https://netbasal.com/optimizing-the-performance-of-your-angular-application-f222f1c16354)). – ConnorsFan Apr 09 '19 at 20:57
  • It will most likely cause performance issues. (It is also not good to have a method get called that many times). I need to put the method in the template because of a I'm using a mat-autocomplete inside a double ngFor. Thanks for the link. If you have suggestions please let me know. – Dave Apr 10 '19 at 13:10
  • My opinion about calling functions in a template is the same as the answers in [this post](https://stackoverflow.com/questions/34842835/is-it-a-bad-practice-to-use-function-call-in-ng-if-ngif): optimize if it causes performance problems. Please note that the answers refer also to Angular 2+ (the `angular` tag was removed later). – ConnorsFan Apr 10 '19 at 13:25