0
votes

In my Angular app in my component i'm making two subscription to two Observables with switchMap that gets data from two API, when the component is opened i have to show a skeleton or a loader and i would prevent it, so i've just read about the Resolve which as i understand preload the data and then activate the route.

So i was wondering on how could i move the following subscription from ngOnInit to a Resolver

Here is how my ngOnInit looks like now

  ngOnInit(): void {
    this.menuService
      .menu(this.idNegozio, this.piva, 'IT')
      .pipe(
        switchMap((menu) =>
          forkJoin([
            of(menu),
            this.pluService.plu(this.idNegozio, this.piva, 'IT'),
          ])
        )
      )
      .subscribe(([menu, plus]) => {
        this.menu = menu;
        this.plus = plus;
        this.filterPlu(menu[0].id);
        if (this.filteredPlu.length) {
          this.ready = true;
        }
      });
  }

And that same component is used in three routes:

  {
    path: 'asporto',
    component: ProductsComponent,
    canActivate: [ItemsGuardService]
  },
  {
    path: 'takeaway',
    component: ProductsComponent,
  },
  {
    path: 'ecom',
    component: ProductsComponent,
  },
1

1 Answers

1
votes

Create a resolver

@Injectable()
export class MenuResolver implements Resolve<Menu>{
    constructor(private menuService: MenuService, private pluService: PluService) {}

    resolve(route: ActivatedRouteSnapshot): Observable<Menu> {
        const piva = route.parent.params.piva;
        const negozio = route.parent.params.negozio;

        return  this.menuService
        .menu(negozio, piva, 'IT')
        .pipe(
          switchMap((menu) =>
            forkJoin([
              of(menu),
              this.pluService.plu(negozio, piva, 'IT'),
            ])
          ),
          map(([menu, plus]) => ({ menu, plus }))
        );
    }
}

Use it in your routes definition and provide it in your parent module

const routes: Routes = [
 {
        path: '',
        resolve: { menu: MenuResolver },
        component: Component,
 }
];

@NgModule({
  imports: [
        RouterModule.forChild(routes),
  ],
  providers: [
    MenuResolver,
  ]
})
export class MyModule { }

Then get it in your component via ActivatedRoute

export class MyComponent {
  menu: Menu;
  plus: MenuDetails;
 
  constructor(private route: ActivatedRoute){}
  
  ngOnInit() {
    const menuData = this.route.snapshot.data.menu;
    this.menu = menuData.menu;
    this.plus = menuData.plus;
  }
}

You will have to add the resolver to all of the concerned routes, and use it the same way in the components