Search code examples
angularangular-services

How to wait for the information to be received by the service and then use it in angular


I wrote a service that receives permissions data from the API, and based on these permissions, I show or hide parts of the menu. But I want it to show or hide parts of the menu only after receiving information from the service. But I don't know how to do it.

permission.service.ts

    import { HttpClient } from '@angular/common/http';
    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs';
    import {ApiConfig} from "../../configs/api.config";
    import {Permission} from "../../interface/permission";

    @Injectable({
      providedIn: 'root'
    })
    export class PermissionService {
      private permissions: Permission[] = [];
    
      constructor(private http: HttpClient) {
        this.initializePermissions();
      }
    
      public fetchPermissions(): Observable<Permission[]> {
        return this.http.get<Permission[]>('api/permissions');
      }
    
      public getPermissions(): Permission[] {
        return this.permissions;
      }
    
      private initializePermissions(): void {
        this.fetchPermissions().subscribe(
          (permissions: Permission[]) => {
            this.permissions = permissions;
          },
          (error) => {
            console.error('Failed to fetch permissions:', error);
          }
        );
      }
    }

I have a sidebar component that use this PermissionService.

import {Component, Inject, OnInit} from '@angular/core';
import {ROUTES_CONFIG} from "../../../../configs/routes.config";
import {SlidebarMenuItem} from "../../../../interface/slidebar-menu-item";
import {PermissionService} from "../../../../shared/services/permission.service";

@Component({
  selector: 'app-sidebar',
  templateUrl: './sidebar.component.html',
  styleUrls: ['./sidebar.component.css'],
})
export class SidebarComponent implements OnInit {

  url: string = '';
  menuItems: SlidebarMenuItem[] = [];

  constructor(@Inject(ROUTES_CONFIG) public routesConfig: any, private permissionService: PermissionService) {

    if(! this.permissionService.getPermissions().length){
        setTimeout(()=>{
            this.initMenuItems();
        }, 1000)
    }
    else{
        this.initMenuItems();
    }
      
  }

  ngOnInit(): void {}

  initMenuItems(){
    this.menuItems = [
      {
        title: 'dashboard',
        icon: 'desktop-mac-dashboard',
        href: null,
        routerLink: this.routesConfig.routes.admin.main,
        node: '',
        children: null,
        show: true,
      },
      {
        title: 'orders',
        icon: 'clipboard-text',
        href: '#',
        routerLink: this.routesConfig.routes.admin.orders,
        node: 'order',
        show: this.permissionService.getPermissions().some((item) => item.name === "read-order"),
        children: null,
      },
    ];
  }
}

Now I want the initMenuItems() method to be executed after fetchPermissions() on PermissionService. How to do that?

I used setTimeout to add delay to using getPermissions() but this is not a logical way, I am looking for a right way.


Solution

  • You only need to subscribe on getPermissions() method like below

    this.permissionService.fetchPermissions().subscribe((permissions) => this.initMenuItems())