Home > Mobile >  angular component doesnt update data to the dom after fetching using api unless i open the component
angular component doesnt update data to the dom after fetching using api unless i open the component

Time:10-31

im using fakeapi store to fetch products and loop on them to show in a component im using a service to do that and it goes as follows

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment';

@Injectable({
  providedIn: 'root',
})
export class ProductsService {
  eleProducts: any[];
  spinnerElec: boolean;
  constructor(private http: HttpClient) {
    this.spinnerElec = true;
    this.eleProducts = [];
  }
  getElectronics() {
    this.spinnerElec = true;
    this.http
      .get(environment.baseUrl   '/category/electronics')
      .subscribe((res: any) => {
        this.eleProducts = res;
        this.spinnerElec = false;
      });
  }

then in the electronics-component.ts

export class ElectronicsComponent implements OnInit {
  Products: any[];
  spinner: boolean;

  constructor(public service: ProductsService) {
    this.Products = [];
    this.spinner = true;
  }

  ngOnInit(): void {
    this.getProducts();
  }

  getProducts() {
    this.spinner = this.service.spinnerElec;
    this.service.getElectronics();
    this.Products = this.service.eleProducts;
  }

and to display data in electronics-component.html

<div  *ngIf="!spinner">
    <div
      
      style="width: 18rem"
      *ngFor="let product of Products"
    >
      <app-product
        [elecCart]="service.elecCart"
        [Product]="product"
        (target)="addToCart($event)"
      ></app-product>
    </div>
  </div>
  <div
    
    *ngIf="spinner"
  >
    <app-spinner></app-spinner>
  </div>

im using ngif on the spinner to clear it from the dom and show data once it fetched sucessfuly the problem is that i must open the componet then go to another component then come back to it again to show the data otherwise the data wont show... thanks in advance

CodePudding user response:

You are not returning anything in getProducts, and you should let the component to subscribe to that http call, not your service. With your current code in the service, even you add a return to it, it will return a Subscription, not the data you want to handle in the component.

I highly recommend the reactive approach, which is a good practice in Angular:

service

getElectronics(): Observable<any[]> { //you should create your own type, avoid using any
  return this.http.get(environment.baseUrl   '/category/electronics').pipe(
   tap(() => this.spinnerElect = false)
  );
}

Component

theProducts$!: Observable<any[]>; //it will store the data wrapped as an Observable

ngOnInit(): void {
  // store the observable from the service containing the products data
  this.theProducts$ = this.service.getElectronics();
}

template HTML

<app-product
  [theProducts]="theProducts$ | async"
  (target)="addToCart($event)"
></app-product>

Using the async pipe, you subscribe to the observable in the template HTML, without managing the subscription.

CodePudding user response:

You are not suscribing in your componen, so as http is an async operation the first time you use call it in ngOnInit the code will continue and don't return anything because your component aren't listening that change.

There are two ways to avoid this, if you are not familiar with Rxjs (as i am) you can use setTimeout to create a little delay allowing your code to "wait" until the call is made.

getProducts() {
    this.spinner = this.service.spinnerElec;
    this.service.getElectronics();  
    setTimeout(() => {
      this.Products = this.service.eleProducts;
    }, 100);
  }

BUT this is a way just for a quick fix. The correct way is to : a) return the http petition to the component and suscribe there.

b) Convert eleproducts in an observable, when the http is load use .next(res) to emit the new value. In your component you'll suscribe to that observable and it will updated

Look here to know more about how to suscribe to a service variable: https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject

  • Related