I have a lazy loaded module with all it components declared and routes added in RouterModule.forChild()
but some of these routes have their resolver that will prefetch some data And call a service to change something in the parent component header like the following:
//Imports...
@Injectable({
providedIn: 'root',
})
export class MyVendorHeaderResolver implements Resolve<Header> {
constructor(private vendorHeaderService: VendorHeaderService) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<Header> {
const title: string = 'MainNav.NavMenu.Vendors.Action.MyVendor';
const breadcrumbs: Breadcrumb[] = [
{ displayText: 'MainNav.NavMenu.Vendors.Title', link: '..' },
{
displayText: 'MainNav.NavMenu.Vendors.Action.MyVendor',
link: route.routeConfig.path,
},
];
//this change the header of the main page component if
this.vendorHeaderService.changeHeader({ title, breadcrumbs } as Header);
// if the pervious line works with the same instance of the service provided in module,
// i'd not need to return anything form this resolver
return of({ title, breadcrumbs } as Header);
}
}
so this VendorHeaderService:
//imports
@Injectable({
providedIn: 'root',
})
export class VendorHeaderService {
private header$ = new Subject<Header>();
constructor() {}
headerChange(): Subject<Header> {
return this.header$;
}
changeHeader(header: Header) {
this.header$.next(header);
}
}
this is the routing module:
const routes: Routes = [
{
path: '',
redirectTo: 'vendors/vendors-categories',
pathMatch: 'full',
},
{
path: 'vendors',
component: VendorsComponent,
children: [
{
path: 'vendors-categories',
component: VendorsCategoriesComponent,
canActivate: [VendorsCategoriesGuard],
resolve: {
header: VendorCategoryHeaderResolver,
categories: VendorsCategoriesResolver,
},
children: [
{
path: 'new',
component: VendorCategoryDialogEntryComponent,
},
{
path: ':vendorCategoryId',
component: VendorCategoryDialogEntryComponent,
canActivate: [VendorCategoryGuard],
resolve: {
categoryDialogData:
VendorCategoryDialogInfoResolver,
},
},
],
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class VendorsAndCustomersRoutingModule {}
I want it to be provided only in my Lazy Loaded Module but I can't cause it used in the resolver.
so my question:
Is it possible to make the resolver service instance is the same one of that used in the module components without exposing the service outside with this provideIn: 'root'?
I've made the services all provided in the 'root' Enviroment Injector and it's working fine, but the service is exposed to any place in the app
If you provide both
VendorHeaderServiceandMyVendorHeaderResolverwithin the lazily loaded feature module instead of at the root level, the service and resolver won't be available throughout the entire app, they will only be accessible within that specific feature module.Then, in your resolver, if you're obtaining the service instance through the constructor, you'll be working with the same instance of the service.
If you're using Angular version 14 or later, an alternative approach can be to inject the same service instance without a constructor function like this:
Angular also allows you to provide your services and resolvers on the route level, in your case you can modify your routes config to look something like this: