Reputation: 2141
I'm implementing lazy-loaded feature modules into my angular 6 app, and have successfully configured one for an 'Invoices' feature, but I'm having issues implementing routing for the lazy-loaded 'Expenses' and 'Contacts' feature modules, which have been set up in the same way as the first.
Each module has been imported into the AppModule, and they also use a SharedModule, which I've imported into the AppModule and each feature module.
When routing to any of the pages using the 'Expenses' or 'Contacts' modules, I receive the following error in the console:
ERROR Error: Uncaught (in promise): Error: RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead. Error: RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead. at provideForRootGuard (vendor.js:106249)
I am using .forChild(routes) for the feature modules, but the only thing I can think of that may be causing this is tangled imports somewhere in the process. Based on previous questions regarding others having this issue, I have checked to see if the AppModule has been imported into any of the other modules, therefore causing forRoot() to be called twice, but this isn't the case.
With the error saying something to do with it being at provideForRootGuard, I thought it could be to do with CanActivateRootGuard being imported into each module, but removing this didn't solve the issue either.
AppRoutingModule:
import { NgModule } from '@angular/core';
import { RouterModule, Routes, RouterLinkActive } from '@angular/router';
import { CanActivateRouteGuard } from './can-activate-route.guard';
// COMPONENTS
// Dashboard
import { DashboardComponent } from './dashboard/dashboard.component';
// Login
import { LoginComponent } from './login/login.component';
// Register
import { RegisterComponent } from './register/register.component';
// Notifications
import { NotificationsComponent } from './notifications/notifications.component';
// Bank
import { BankComponent } from './bank/bank.component';
// Documents
import { DocumentsComponent } from './documents/documents.component';
const routes: Routes = [
{
path: '',
redirectTo: 'login',
pathMatch: 'full'
},
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [CanActivateRouteGuard]
},
// Login/Register
{
path: 'login',
component: LoginComponent
},
{
path: 'register',
component: RegisterComponent
},
// Notifications
{
path: 'notifications',
component: NotificationsComponent,
canActivate: [CanActivateRouteGuard]
},
{
path: 'notifications/:id',
component: NotificationsComponent,
canActivate: [CanActivateRouteGuard]
},
// Bank
{
path: 'bank',
component: BankComponent,
canActivate: [CanActivateRouteGuard]
},
// Contacts
{
path: 'contacts',
loadChildren: './contacts/contacts.module#ContactsModule'
},
// Expenses
{
path: 'expenses',
loadChildren: './expenses/expenses.module#ExpensesModule'
},
// Invoices
{
path: 'invoices',
loadChildren: './invoices/invoices.module#InvoicesModule'
},
// Documents
{
path: 'documents',
component: DocumentsComponent,
canActivate: [CanActivateRouteGuard]
}
]
@NgModule ({
imports: [
RouterModule.forRoot(routes)
],
exports: [
RouterModule
]
})
AppModule
// ANGULAR CORE
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
// FEATURE MODULES
import { ContactsModule } from '@app/contacts/contacts.module';
import { ExpensesModule } from '@app/expenses/expenses.module';
import { InvoicesModule } from '@app/invoices/invoices.module';
import { BankModule } from '@app/bank/bank.module';
import { DocumentsModule } from '@app/documents/documents.module';
// MATERIAL MODULE
import { MaterialModule } from '@app/material.module';
// SHARED MODULE
import { SharedModule } from '@app/shared.module';
// COMPONENTS
import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard/dashboard.component'
// Account
import { LoginComponent } from './login/login.component'
import { RegisterComponent } from './register/register.component'
import { VerifyEmailDialogComponent } from './register/dialogs/verify-email-dialog/verify-email-dialog.component';
// Notifications
import { NotificationsComponent } from './notifications/notifications.component';
@NgModule({
declarations: [
AppComponent,
// COMPONENTS
// Dashboard
DashboardComponent,
// Login
LoginComponent,
// Register
RegisterComponent,
// Dialogs
VerifyEmailDialogComponent,
// Notifications
NotificationsComponent
],
imports: [
// ANGULAR CORE
BrowserModule,
BrowserAnimationsModule,
// FEATURE MODULES
InvoicesModule,
ContactsModule,
ExpensesModule,
BankModule,
DocumentsModule,
// MATERIAL MODULE
MaterialModule,
// SHARED MODULE
SharedModule
],
entryComponents: [
// DIALOGS
// Register
VerifyEmailDialogComponent
],
providers: [
],
bootstrap: [AppComponent]
})
export class AppModule { }
ExpensesRoutingModule
import { NgModule } from '@angular/core';
import { RouterModule, Routes, RouterLinkActive } from '@angular/router';
// import { CanActivateRouteGuard } from '@app/can-activate-route.guard';
// COMPONENTS
import { NewExpenseComponent } from './new-expense/new-expense.component';
import { ExpenseListComponent } from './expense-list/expense-list.component';
import { ViewExpenseComponent } from './view-expense/view-expense.component';
const routes: Routes = [
{
path: 'expenses/new',
component: NewExpenseComponent,
// canActivate: [CanActivateRouteGuard]
},
{
path: 'expenses/all',
component: ExpenseListComponent,
// canActivate: [CanActivateRouteGuard]
},
{
path: 'expenses/:id',
component: ViewExpenseComponent,
// canActivate: [CanActivateRouteGuard]
},
]
@NgModule({
imports: [
RouterModule.forChild(routes)
],
exports: [
RouterModule
]
})
export class ExpensesRoutingModule {
}
ExpensesModule
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ExpensesRoutingModule } from './expenses-routing.module';
// SHARED/MATERIAL MODULES
import { SharedModule } from '@app/shared.module';
import { MaterialModule } from '@app/material.module';
// COMPONENTS
// New Expense
import { NewExpenseComponent } from './new-expense/new-expense.component';
// Expense List
import { ExpenseListComponent } from './expense-list/expense-list.component';
// View Expense
import { ViewExpenseComponent } from './view-expense/view-expense.component';
// Dialogs
import { DeleteExpenseDialogComponent } from './view-expense/dialogs/delete-expense-dialog/delete-expense-dialog.component';
@NgModule({
imports: [
CommonModule,
ExpensesRoutingModule,
SharedModule,
MaterialModule
],
declarations: [
// COMPONENTS
// New Expense
NewExpenseComponent,
// Expense List
ExpenseListComponent,
// View Expense
ViewExpenseComponent,
// Dialogs
DeleteExpenseDialogComponent
],
entryComponents: [
// DIALOGS
// View Expense
DeleteExpenseDialogComponent
]
})
export class ExpensesModule {
}
SharedModule Routing Imports
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
// ROUTING
import { AppRoutingModule } from './app-routing.module';
import { RouterLinkActive, CanActivate } from '@angular/router';
import { CanActivateRouteGuard } from './can-activate-route.guard';
...
Upvotes: 1
Views: 6796
Reputation: 2141
FIX
Managed to fix this by removing the AppRoutingModule
from the SharedModule
and into the AppModule
instead. All routes now working fine.
Upvotes: 7
Reputation: 2290
You are including your AppRoutingModule
in the SharedModule
.
and you load this shared module from your feature modules (like ExpensesModule
)
So you are actually loading it twice.
To fix that, you have to take this out from the shared module. If you have any shared routes you like to keep, just separate it different files, keep the core Routes outside the shared module and include it with forRoot only to your main module.
Upvotes: 3