I currently have an issue with lazy laoded modules and services which are providedIn
this lazy-loaded module.
I have a folder structure looking like this:
app
-> featureModule1 (lazy loaded)
-> featureModule2 (lazy loaded)
-->services
--->service1.ts
I want this service1.ts only be available in featureModule2. So i included @Injectable
// service.ts
@Injectable({
providedIn: featureModule2
})
export class service1 { /* some logic */ }
When i try to route to this lazy loaded module i get an console error:
// console
ERROR Error: Uncaught (in promise): ReferenceError: Cannot access 'featureModule2' before initialization
ReferenceError: Cannot access 'featureModule2' before initialization
My current lazy load route looks like this:
// app-routing.module.ts
const routes: Routes = [
{path: '', redirectTo: '', pathMatch: 'full'},
{ path: 'feature1', loadChildren: () => import('./feature1/feature1.module').then(m => m.featureModule1) },
{ path: 'feature2', loadChildren: () => import('./feature2/feature2.module').then(m => m.featureModule2) }
];
I tried to provide it in the module:
// featureModule1
@NgModule({
declarations: [
featureComponent
],
imports: [
...
],
providers: [
service1
]
})
That doesn't work.
And i tried to import the service1.ts directly a component (featureComponent
).
// featureComponent
import { service1 } from '../featureModule2/services/service1.service';
@Component({
...
})
export class featureComponent {
constructor(private service1: service1) { }
ngOnInit(): void {
this.service1.init();
}
}
This approach lead to the same error message.
The only way to get around this issue at the moment is to create a "wrapper" module which imports all other modules with @Injectable
services.
Is there a different way for this problem? The services in each module should not be injected in root
or any
because they should only be available in each featureModule.
You just have to declare it in providers
section and it will work. I have used useFactory
provider variant in order to clearly show that it is used in order to perform injection and angular is not simply new LazyService
just in place. I will work with providers:[LazyService]
as well (which is a 'class provider' I belive, equal to useClass:LazyService
)
In lazy module
import {
CustomerListComponent,
LazyService
} from './customer-list/customer-list.component';
@NgModule({
imports: [CommonModule, CustomersRoutingModule],
declarations: [CustomerListComponent],
providers: [
{
provide: LazyService,
useFactory: () => new LazyService('proofThatItIsFromPRoviders')
}
]
})
export class CustomersModule {}
in lazy component from the same module ("printsLazy service works proofThatItIsFromPRoviders")
export class LazyService {
constructor(private test: string) {}
public say() {
console.log('Lazy service works', this.test);
}
}
@Component({
selector: 'app-customer-list',
templateUrl: './customer-list.component.html',
styleUrls: ['./customer-list.component.css']
})
export class CustomerListComponent implements OnInit {
constructor(private lazy: LazyService) {}
ngOnInit() {
this.lazy.say();
}
}
injection in different module fails
@Component({
selector: 'app-order-list',
templateUrl: './order-list.component.html',
styleUrls: ['./order-list.component.css']
})
export class OrderListComponent implements OnInit {
constructor(private lazy:LazyService) { }
ngOnInit() {
this.lazy.say();
}
}
Working example here https://stackblitz.com/edit/angular-s5xxnb-j9ch1z?file=src%2Fapp%2Forders%2Forder-list%2Forder-list.component.ts
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With