1

I have a nested loop in a table, but i want to only show a limited amount of rows in the DOM and load more when a button is clicked.

The Loop looks something like this:

<ng-container *ngFor="let organisation of organisations; let organisationIndex = index;">
    <ng-container *ngFor="let department of organisation.departments; let departmentIndex = index;">
        <ng-container *ngFor="let user of department.users; let userIndex = index;">
            <div>
                This is a List entry and i only want this 20 times in total (not for each loop)
            </div>
        </ng-container>
    </ng-container>
</ng-container>

What would be the smoothest way to get the index inside the nested loop, if possible without adding complexity?

I do not want to do it with css :nth-of-type or something similiar since my dataset is huge and the dom gets slow even if elements are hidden with css.

The length of each arrays is dynamic which prevents me from making a static formula (like organisationIndex * 50).

1 Answer 1

3

There are multiple options how you can deal with this one:

Server pre-processing Trim the data on the server and send to client only set you would like to render. The advantage is the client's browser does not have to deal with large amount of data (and download them). Or introduce a "totalIndex" on each user that is incremental and continuous over organisations.

Angular trimming - equal number of items in sub-collections

If your items in your sub-collections contain the same number of items. You have to multiply the indexes and check whether you already output 20 rows. If so use *ngIf to avoid showing more of them. When using *ngIf item is not rendered at all.

<ng-container *ngFor="let organisation of organisations; let organisationIndex = index;">
    <ng-container *ngFor="let department of organisation.departments; let departmentIndex = index;">
        <ng-container *ngFor="let user of department.users; let userIndex = index;">
            <div *ngIf="(organisationIndex * organisation.departments.length) + (departmentIndex * department.users.length) + userIndex < 20">
                This is a List entry and i only want this 20 times
            </div>
        </ng-container>
    </ng-container>
</ng-container>

Angular trimming - counterpipe If number of items in sub-collections is not equal use counterpipe.

import { Pipe, PipeTransform } from '@angular/core';
import { Counter } from './counter';

const counters = new WeakMap<any, Counter>();

@Pipe({
  name: 'counterPipe'
})
export class CounterPipe implements PipeTransform  {
  transform(value: any): Counter {
    if (!counters.has(value)) {
      counters.set(value, new Counter());
    }
    return counters.get(value);
  }
}

This will add counter while processing entities in *ngFor so you always know the number of element you are rendering.

Wrap your code with this pipe:

<ng-container *ngFor="let counter of [organisations | counterPipe]">
  <ng-container *ngFor="let organisation of organisations; let organisationIndex = index;">
      <ng-container *ngFor="let department of organisation.departments; let departmentIndex = index;">
          <ng-container *ngFor="let user of department.users; let userIndex = index;">
              <div *ngIf="counter.inc() < 20">
                This is a List entry and i only want this 20 times
              </div>
          </ng-container>
      </ng-container>
  </ng-container>
</ng-container>

Example of usage can be seen on https://stackblitz.com/edit/angular-nested-ngfor-ydvxjv

Sign up to request clarification or add additional context in comments.

9 Comments

But wouldnt this slice just limit the most inner Array? i would like to have 20 entries in total not per department. Ill adjust my question to state that i want 20 entrie sin total.
so move slice on the top *ngFor ... I have adjusted my answer.
This will not show 20 entries if you have 20 organisations with 10 departments each and 10 users pre department (just as an example of content of the arrays. No matter which *ngfor you limit you will not be able to slice the end result of entries
@JeremiasNater now I understand what you mean. You just need 20 records no matter what the level is. Let me change the answer for you.
@JeremiasNater I have changed the answer according to your explanation.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.