Query asked by user
I’ve got a published library containing a component that uses [routerLink] in it’s template. After installing the library in my application, I get the error NullInjectorError: R3InjectorError(AppModule)[Router -> Router -> Router]:
NullInjectorError: No provider for Router!
Within the module in the library the RouterModule is imported and looks like this:
@NgModule({
declarations: [
Component
],
exports: [
Component
],
imports: [
CommonModule,
RouterModule,
TranslateModule
]
})
export class LibWithComponentModule {
}
Within my application, the RouterModule is configured as follows:
const routes: Routes = [{
path: '',
component: RootComponent
}];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
The app.module.ts
looks like this:
declarations: [
AppComponent,
RootComponent
],
imports: [
BrowserModule,
AppRoutingModule,
LibWithComponentModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
But I thought the RouterModule is going to be provided? What am I doing wrong?
Answer we found from sources
I was facing this exact same scenario you described in a large application I’m working on. My main application imports a published npm component package that contains a component that leverages the routerLink
directive. When running the application, I run into the same R3InjectorError
you mention, even though RouterModule
is definitely correctly imported in all modules that need it.
The root cause of the problem in my case, was the fact that this npm package explicitly listed @angular/router
as one of the dependencies
instead of a peerDependency
(which in the case of a library it should have been). This means @angular/router
will be installed both in your node_modules
, as well as in node_modules/LIBRARY/node_modules
!
What happens is that at runtime, the RouterModule
your published component uses has a different InjectionToken
than the RouterModule
your application provided using a RouterModule.forRoot()
. The published component’s RouterModule
refers to node_modules/LIBRARY_NAME/node_modules/@angular/router
, whereas the main application has provided the one in node_modules/@angular/router
.
So in conclusion: the fix is to not explicitly have any @angular
packages listed in your library as a dependency
, but correctly mark them as a peerDependency
. Here’s an interesting read on managing dependencies from the ng-packagr
documentation.
For reference: I’m not sure if this exclusively Ivy related, but in my scenario I was running Angular 11 with Ivy enabled.
The error message is definitely very confusing in this case, as the injected service is named Router
twice, even though they’re referencing different instances.
Hope this solves your problem too, I spent quite some time to figure this out!
Answered By – Nils Tijtgat
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0