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 class="row gap-3 justify-content-center" *ngIf="!spinner">
<div
class="card col-lg-4 col-md-6 col-sm-12 bg-warning"
style="width: 18rem"
*ngFor="let product of Products"
>
<app-product
[elecCart]="service.elecCart"
[Product]="product"
(target)="addToCart($event)"
></app-product>
</div>
</div>
<div
class="spin d-flex justify-content-center align-items-center w-100"
*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
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