I am building an angular 6 application where I have two separate screens:
My application is based on modules, so I have
Each module has empty component containing just an outlet, except the layout(containing header, body and footer).
I want to achieve those routes:
site.com/account/login
site.com
| will navigate to the dashboard
site.com/dashboard
site.com/products
site.com/invoices
Visual explanation
I have no problem with adding the account.module
, but I don't know how to configure the routes when adding the layout.module
Note: maybe my whole approach is wrong, but to me it is the only logical thing to do, since I have modules containing components, and I want to be prepared for possible lazy loading configuration.
Please advice me If I'm on the wrong path.
Code
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { LayoutModule } from './layout/layout.module';
import { AccountModule } from './feature-components/membership/account.module';
@NgModule({
declarations: [
AppComponent,
FetchDataComponent
],
imports: [
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
BrowserAnimationsModule,
HttpClientModule,
LayoutModule,
AccountModule,
BrowserAnimationsModule
RouterModule.forRoot([
{ path: '', component: LayoutOutletComponent },
{ path: '**', component: PageNotFoundComponent }
]),
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.html
<router-outlet></router-outlet>
account.module.ts
import { NgModule } from '@angular/core';
import { SharedModule } from '@app-shared/shared.module';
import { LoginComponent } from './login/login.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { ChangePasswordComponent } from './change-password/change-password.component';
import { RouterModule } from '@angular/router';
import { AccountOutletComponent } from './account-outlet/account-outlet.component';
@NgModule({
imports: [
SharedModule,
RouterModule.forChild(
[{
path: 'account', component: AccountOutletComponent,
children: [
{ path: 'login', component: LoginComponent },
{ path: 'reset-password', component: ResetPasswordComponent },
{ path: 'change-password', component: ChangePasswordComponent },
{ path: '', redirectTo: 'login', pathMatch: 'full' }
]
}]
)
],
exports: [
LoginComponent,
ResetPasswordComponent,
ChangePasswordComponent
],
declarations: [
AccountOutletComponent,
LoginComponent,
ResetPasswordComponent,
ChangePasswordComponent
]
})
export class AccountModule { }
So, no problems here, the problems starts when I add that layout module
which should constants the layout and inside of it, all nested modules.. and to be honest I don't even know how to start the routing configuration
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { FooterComponent } from './footer/footer.component';
import { LayoutOutletComponent } from './layout-outlet/layout-outlet.component';
import { InvoicesModule } from '../feature-components/invoices/invoices.module';
@NgModule({
imports: [
CommonModule,
InvoicesModule,
RouterModule
)],
exports: [
NavMenuComponent,
FooterComponent
],
declarations: [
NavMenuComponent,
FooterComponent,
LayoutOutletComponent
]
})
export class LayoutModule { }
Angular Router supports multiple outlets in the same application. A component has one associated primary route and can have auxiliary routes.
You can have multiple router-outlet in same template by configuring your router and providing name to your router-outlet, you can achieve this as follows. Advantage of below approach is thats you can avoid dirty looking URL with it. eg: /home(aux:login) etc.
Remember all this route config only has one router-outlet , so the end result of the matching must be a single component and not multiple.
The Angular router-outlet Router-Outlet is an Angular directive from the router library that is used to insert the component matched by routes to be displayed on the screen.
I think you're on the right path. First you need to deal with eager routes and then you can switch to lazy modules.
What you need to do:
app.module.ts
@NgModule({
imports: [
BrowserModule,
AccountModule,
LayoutModule,
RouterModule.forRoot([
{ path: '**', component: PageNotFoundComponent }
])
],
declarations: [
AppComponent,
PageNotFoundComponent
],
bootstrap: [AppComponent]
})
export class AppModule { }
layout.module.ts
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([
{
path: '',
component: LayoutOutletComponent,
children: [
{
path: 'dashboard',
loadChildren: () => DashboardModule
},
{
path: 'products',
loadChildren: () => ProductsModule
},
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' }
]
}
])
],
declarations: [
LayoutOutletComponent
]
})
export class LayoutModule { }
The main thing you need to know is that all angular routes are merged in one route configuration. To understand this I'd suggest you watching a great video by @deborahk
You can't just write
{ path: '', component: LayoutOutletComponent},
and import other modules(ProductsModule
, DashboardModule
) separately. The nested routes should be provided as child routes.
Now, when you have all routes configured you can easily switch to lazy loaded modules:
{
path: '',
component: LayoutOutletComponent,
children: [
{
path: 'dashboard',
loadChildren: 'pathToModule#DashboardModule'
},
{
path: 'products',
loadChildren: 'pathToModule#ProductsModule'
},
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' }
]
}
And also you can lazy load LayoutModule in AppModule
@NgModule({
imports: [
...
LayoutModule,
RouterModule.forRoot([
{ path: '', loadChildren: './layout/layout.module#LayoutModule' },
{ path: '**', component: PageNotFoundComponent }
])
],
...
})
export class AppModule { }
I've created ng-nested-outlets app on github so try it out.
You can also try it online on Stackblitz Demo
See also
You shoud do the following things
app.module
RouterModule.forRoot([
{ path: '', loadChildren: '(PathToLayoutMoudle)#LayoutModule' },
{ path: '**', component: PageNotFoundComponent }
]),
layout.module
RouterModule.forChild([
{ path: '', component: LayoutComponent},
children: [
{ path: 'dashboard',loadChildren:
PathToDashboardMoudle)#DashboardMoudle'},
{ path: 'products',loadChildren:
PathToProductsMoudle)#ProductsMoudle'},
{ path: 'invoices',loadChildren:
PathToInvoicesMoudle)#InvoicesdMoudle'},
]
]),
account.module
RouterModule.forChild(
[{
path: '', component: AccountOutletComponent,
children: [
{ path: 'login', component: LoginComponent },
{ path: 'reset-password', component: ResetPasswordComponent },
{ path: 'change-password', component: ChangePasswordComponent },
{ path: '', redirectTo: 'login', pathMatch: 'full' }
]
}]
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