Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RouterModule.forRoot called twice

I am trying to implement Lazy Loading into my application but seem to be coming across an issue whereby I get the error message :

Error: RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.

So I have my main app-routing.module.ts and also app-module.ts which looks like below:

app-module.ts

// External Dependencies import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { HttpClientModule } from '@angular/common/http'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations';  // Internal Dependencies import { MaterialModule } from '../app/configuration/material/material.module'; import { SharedModule } from '../app/application/shared/shared.module'; import { RoutingModule } from '../app/configuration/routing/routing.module'; import { SettingsModule } from '../app/application/settings/settings.module';  import { AppComponent } from './app.component';  import { SearchService } from './application/shared/services/search.service';  @NgModule({   declarations: [AppComponent],   imports: [     BrowserAnimationsModule,     BrowserModule,     SharedModule,     RoutingModule,     MaterialModule,     HttpClientModule,     FormsModule,   ],   providers: [ ],   bootstrap: [AppComponent] })  export class AppModule { } 

app-routing.ts

// External Dependencies import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule, Routes } from '@angular/router'; import { HttpModule } from '@angular/http';  const appRoutes: Routes = [   { path: '', redirectTo: 'overview', pathMatch: 'full' },   { path: 'overview', loadChildren: '../../application/overview/overview.module#OverviewModule' },   { path: 'search', loadChildren: '../../application/search/search.module#SearchModule' },     { path: 'policy/:id', loadChildren: '../../application/policy/policy.module#PolicyModule' },   { path: 'claim/:id', loadChildren: '../../application/claim/claim.module#ClaimModule' },   { path: 'settings', loadChildren: '../../application/settings/settings.module#SettingsModule' } ];  @NgModule({   imports: [     CommonModule,     RouterModule.forRoot(appRoutes)   ],   exports: [     RouterModule   ],   declarations: [] })  export class RoutingModule { } 

This works fine and the application correctly loads. The issue from here is that in the SharedModule it has come components to redirect the user using routerLink to a new page.

shared.module.ts

// External Dependencies import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { CalendarModule } from 'primeng/calendar'; import { AgmCoreModule } from '@agm/core'; import { FroalaEditorModule, FroalaViewModule } from 'angular-froala-wysiwyg'; import { PdfViewerModule } from 'ng2-pdf-viewer';  // Internal Dependencies import { MaterialModule } from '../../configuration/material/material.module'; import { RoutingModule } from '../../configuration/routing/routing.module';  import { NavbarTopComponent } from '../../application/shared/components/navbar-top/navbar-top.component'; import { NavbarSideComponent } from './components/navbar-side/navbar-side.component'; import { TemplateCardWComponent } from './components/template-card-w/template-card-w.component'; import { FilterPipe } from './pipes/filter.pipe'; import { StandardTableComponent } from './components/standard-table/standard-table.component'; import { OrderPipe } from '../shared/pipes/order.pipe'; import { ActionComponent } from './components/action/action.component'; import { GoogleMapComponent } from './components/google-map/google-map.component'; import { HtmlEditorComponent } from './components/html-editor/html-editor.component'; import { PdfViewerComponent } from './components/pdf-viewer/pdf-viewer.component'; import { KeyBindingPipe } from './pipes/key-binding.pipe'; import { StandardEditTableComponent } from './components/standard-edit-table/standard-edit-table.component';  @NgModule({   imports: [     CommonModule,     MaterialModule,     RoutingModule,     FormsModule,     CalendarModule,     AgmCoreModule,     FroalaEditorModule,     FroalaViewModule,     PdfViewerModule   ],   declarations: [     NavbarTopComponent,     NavbarSideComponent,     TemplateCardWComponent,     FilterPipe,     StandardTableComponent,     OrderPipe,     ActionComponent,     GoogleMapComponent,     HtmlEditorComponent,     PdfViewerComponent,     KeyBindingPipe,     StandardEditTableComponent   ],   exports: [   ] })  export class SharedModule { } 

As you can see I am having to import the RouterModule. If I remove the RouterModule, the application will load but no re-direct. If I keep the RouterModule the application will cause the error at the top of the question.

Could anyone help me on this.

like image 931
Ben Clarke Avatar asked Apr 05 '18 10:04

Ben Clarke


People also ask

What is the difference between RouterModule forRoot () and RouterModule forChild ()?

forRoot creates a module that contains all the directives, the given routes, and the router service itself. forChild creates a module that contains all the directives and the given routes, but does not include the router service.

What is the RouterModule forRoot method used for?

The forRoot() method creates an NgModule that contains all the directives, the given routes, and the Router service itself. The forChild() method creates an NgModule that contains all the directives and the given routes, but does not include the Router service.

What does forRoot mean?

The forRoot static method is the method that configures the root routing module for your app. When you call RouterModule. forRoot(routes) , you are asking Angular to instantiate an instance of the Router class globally.

How lazy loading works in Angular?

Lazy loading is a technique in Angular that allows you to load JavaScript components asynchronously when a specific route is activated. It improves the speed of the application load time by splitting the application into several bundles. When the user navigates through the app, the bundles are loaded as required.


2 Answers

I got this error because I somehow accidentally imported the root AppModule into my lazy-loaded module. This caused the root AppRoutingModule to be called again when the lazy-loaded module was loaded, and thus RouterModule.forRoot was called twice.

If you are certain you aren't calling RouterModule.forRoot twice then this could be the cause of the issue. Check that you aren't importing any modules in your lazy-loaded module that direcly call RouterModule.forRoot or import a module that calls RouterModule.forRoot.

like image 50
inorganik Avatar answered Sep 20 '22 09:09

inorganik


I've been struggling with this for a while. Finally found the issue.

I'm using lazy loading. And even though I'd only used .forRoot in one place in the app, the error suggested that I was using it twice.

Turned out that I was importing the AppRoutingModule from app.routing.ts file in one of the feature modules that was being lazy loaded. And I had done this earlier because it kept saying it didn't recognize routerLink which I had used in one of the components in that feature module.

The solution was to replace the AppRoutingModule import in the feature module with an import of the RouterModule from '@angular/router'. Now everything works.

PS - when I say feature module, I mean sub module that I'm lazy loading.

like image 38
Ragav Y Avatar answered Sep 21 '22 09:09

Ragav Y