Home > Software design >  Angular 14 : Wait for a service variable to be loaded before loading a component
Angular 14 : Wait for a service variable to be loaded before loading a component

Time:12-01

I use lazy-loading modules, when I arrive on a page of my module, I use functions of a service which performs actions on a global variable of this service.

I have a function that load this global variable from my service. The problem is that no matter where I call this function in my module, the variable is not filled fast enough on the first display, and so I get errors because my variable is empty on the first display.I'm

I tried loading my variable in my module's constructor, but it still doesn't fill the variable fast enough for the first display.

In my service :

export class ReferenceService {

    parts: any;

    constructor(
        private http: HttpClient
    ) { }

    loadParts() {
        this.http.get(apiUrl.partsGet).subscribe(data => this.parts = data);
    }

    getParts() {
        return this.parts;
    }

}

In my module :

export class LaserfibreModule {
    constructor(private apiReference: ReferenceService) {
        this.apiReference.loadParts();
    }
}

In my component : console.log(this.apiReference.getParts()) // return undefined

I would like to find a way so that my component does not display until this variable "parts" is not filled

I found a temporary solution which is to call my "loadParts()" function in my app.component.ts, which works but if I do that, it's not really lazy loading anymore

I tried to use an APP_INITIALIZER in the provider of my module but it does not work

CodePudding user response:

Whether this answer will work is going to depend on how you have architected your Angular application, but you could potentially use a route resolver service. Route resolvers are used to prefetch data when routing to a component.

Here's a basic example of a route resolver service:

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

import { Observable } from 'rxjs/Observable';

import { IProduct } from './product';
import { ProductService } from './product.service';

@Injectable()
export class ProductResolver implements Resolve<IProduct> {

    constructor(private productService: ProductService) { }

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<IProduct> {
        let id =  route.params['id'];
        return this.productService.getProduct(id);
    }
}

You can read the full docs here. There's more detail on how to wire it up, as the resolver needs to be added to the route definition for the component.

If you aren't using routing, or the above isn't suitable, another option would be to render the part of the component's template that is dependent on the data being populated when it's ready (you could show a loading spinner or something until then). You can use a simple *ngIf to achieve this - e.g:

<div *ngIf="parts">
 {{ parts.name }}
</div>
  • Related