1

(Following the suggestion so gunnar, i'm editing my question) @Gunnar.B

Service for connection with api

@Injectable({
  providedIn: 'root'
})
export class ConsolidadoApi {
  constructor(private http: HttpClient) { }
  getInvestiments(search?: any): Observable<any> {
    return this.http.get<any>(`${environment.basePosicaoConsolidada}`);
  }
}

This service (layer) exposes the streams of state and interface for the components in the presentation layer(component)

@Injectable({
    providedIn: 'root'
})
export class CoreService {

    constructor(private api: ConsolidadoApi, private state: StateService) { }

    public getInvestments$(): Observable<any> {
        return this.state.getInvestiments$()
    }

    public loadInvestments() {
        return this.api.getInvestiments()
        .pipe(
            tap(investPortifolio => this.state.setInvestments(investPortifolio))
        );
    }
}

This service is responsible for the logic that will go to the component

@Injectable({
  providedIn: 'root'
})
export class StateService {

  private investments$ = new BehaviorSubject<any>(null);

  public getInvestiments$() {
    return this.investments$.asObservable()
  }

  public setInvestments(investPortifolio){
    this.investments$.next(investPortifolio)
  }
}

However in my html does not appear the data coming from the api.

menu.component.ts

export class MenuComponent implements OnInit {
  
  investments$: Observable<any>;

  constructor( private coreService : CoreService ) {
    this.investments$ = this.coreService.getInvestments$()
   }


  ngOnInit(): void {
    this.coreService.loadInvestments();
    console.log(this.coreService.loadInvestments())
  }

}

menu.component.html

    <div>
        test
    </div>

    <div *ngFor="let investimentPortifolio of investments$ | async;">
        {{investimentPortifolio | json}}
    </div>

enter image description here

Guilherme Lucas
  • 497
  • 6
  • 14
  • This is a timing problem. Have a look at https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call – Gunnar B. Sep 30 '21 at 14:12
  • Anyways I'd suggest to not store a fixed property in the service, but provide the value as an observable as well which components can subscribe to (possibly using the `async pipe`). Have a search for behaviorsubject and asobservable. – Gunnar B. Sep 30 '21 at 14:16
  • I researched what you said, do you know why the data doesn't appear on the screen? – Guilherme Lucas Sep 30 '21 at 15:27
  • You need to call subscribe on this.coreService.loadInvestMents() – Lee Sep 30 '21 at 17:16

1 Answers1

0

listInvestments method is performing an asynchronous API call. So basically the investments property still have undefined when you called forEach on it.

You want to loop in investments array after you load data from the server not before.

One way to do it is to make sure you are inside subscribe's next() callback and there you are certain you have the data you need to perform your action.

CoreService class becomes:

@Injectable({
    providedIn: 'root'
})
export class CoreService {
    public investments: any;
    constructor(private api: ConsolidadoApi, private state: StateService) {}

    public createMenu(){
      this.api.getInvestments()
            .subscribe(response => {
                this.investments = response;
                this.investments.forEach(element => {
                  console.log(element)
                });
            })
       
    }
}

Update on question edit

In ngOnInit you called loadInvestments() that returns an observable. And observable are lazy, that means if you didn't call subscribe on them nothing will happen.

What you need to do is change this line:

this.coreService.loadInvestments();

to

this.coreService.loadInvestments().subscribe();
  • First of all, I would like to thank you for the answer. But I had already tried that way when I called createMenu() in the component it comes undefined, would you know how to fix it? – Guilherme Lucas Sep 30 '21 at 15:25
  • The original question was edited so I will update my answer. – Saber Bjeoui Sep 30 '21 at 16:26
  • interesting but how can i put the data in html? – Guilherme Lucas Sep 30 '21 at 17:22
  • @GuilhermeLucas In general, using the `async pipe` will, under the hood, just give you the 'value' of the observable to use in the html template (the pipe performs a subscribe an give you that to use as template variable). Now, from the looks of it you are just storing the plain json response and try to display that. If that is meant to be an object whichs properties you want to access separately, you'll need to deserialize the json into a javascript object. If you ware not familiar with that, have a look at the angular tutorial (6.): https://angular.io/tutorial – Gunnar B. Oct 01 '21 at 10:49