cheshire
cheshire

Reputation: 1159

How to have nested ngfor with dynamic calls to api

I have an array of object that I get back at once from my API and I display them in .component.html like this:

<div *ngFor="let obj of ObjectArray">
    <div>{{obj.name}}</div>
</div>

I need to make second call to API with each one of the objects where I will populate second object array and will need to display it underneath obj.name and I tried to do that like this:

<div *ngFor="let obj of ObjectArray">
    <div data-dummy="{{populateAnotherObjectArray(obj.id)}}"></div>
    <div>{{obj.name}}</div>
    <div *ngFor="let anotherObj of AnotherObjArray">
        {{anotherObj.name}}
    </div>
</div>

populateAnotherObjectArray(obj.id) is a function in component.ts file where I populate AnotherObjArray.

Now I only get endless calls to second API.

I tried to user Directive and EventEmitter but I don't get anything there.

Is there a simple way to do this?

Update:

Lets say 1st call to API I get in ObjectArray:

[obj1From1stArray, obj2From1stArray]

now I call API again this.api.populate2ndArray(obj1From1stArray.id) and get in AnotherObjecArray:

[obj1From2ndArray]

and after that this.api.populate2ndArray(obj2From1stArray.id) and get in AnotherObjecArray:

[obj2From2ndArray]

What I get on my .html page with current answer:

obj1From1stArray name
    obj1From2ndArray
    obj2From2ndArray
obj2From1stArray name
    obj1From2ndArray
    obj2From2ndArray

What I want:

obj1From1stArray name 
    obj1From2ndArray
obj2From1stArray name
    obj2From2ndArray

Upvotes: 0

Views: 640

Answers (1)

Barremian
Barremian

Reputation: 31125

Try to avoid calling functions inside directives and interpolations as much as possible. If you aren't controlling the change detection strategy, they will be called too many times. You could trigger the call in the controller before displaying the data. Try the following

Controller

import { forkJoin, of } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';

ngOnInit() {
  this.apiService.getObjectArray().pipe(
    switchMap(arr1 => {
      this.ObjectArray = arr1;
      return forkJoin(arr1.map(item => this.apiService.getAnotherObjArray(item['id'])));
    }),
    catchError(err1 => {
      // handle error
      return of(err1);
    })
  ).subscribe(
    arr2 => {
      this.ObjectArray.forEach(obj, index => this.ObjectArray['AnotherObjArray'] = arr2[index]);
    },
    err2 => {
      // handle error
    }
  );
}

Template

<div *ngFor="let obj of ObjectArray">
  <div>{{obj.name}}</div>
  <div *ngFor="let anotherObj of obj.AnotherObjArray">
    {{anotherObj.name}}
  </div>
</div>

Upvotes: 1

Related Questions