I am following this tutorial to have an architecture of my application.
To give more information lets consider A
as appModule, and B
is another main module. Now I want to load other modules (NgModule
which has many other routes) inside B's <router-outlet>
.
What is a better approach to do this?
This is what I have done so far
-mainBoard (Folder next to app.Module)
--mainBoard Routes
--mainBoard Component
--mainHeader Component
--mainFooter Component
--mainSidenav Component
-Users (Folder inside mainBoard)
--User Module
--User Routes
--UserList Component
--UserDetail Component
--UserSetting Component
-Departments (Folder inside mainBoard)
--Department Module
--Department Routes
--DepartmentList Component
--DepartmentDetail Component
-Auth (Folder next to mainBoard folder)
--Auth Module
--Auth Component
--Auth Routes
-Sign-in (Folder)
--Sign-in Component
-Sign-up (Folder)
--Sign-up Component
-App Module
I have 2 main modules, mainBoard and Auth.
MainBoard has a header, sidenav,footer and in the center I want to load Users and Department using <router-outlet>
.
I want to load localhost/app/users
to load Userslist and localhost/app/department
to load department list.
My main-board.module and users.module look like this
// main-board.module.ts
import {MainBoardRouting} from './main-board.routes';
import {UsersModule} from './users/users.module';
import {DepartmentsModule} from './departments/departments.module';
@NgModule({
imports :[
MainBoardRouting,
UsersModule,
DepartmentsModule
],
declarations : [
MainBoardComponent,
MainHeaderComponent,
MainFooterComponent,
MainSidenavComponent
],
providers: []
})
export class MainBoardModule{}
// Users.module.ts
import {NgModule} from '@angular/core';
import {usersRouting} from './users.routes';
import {UserListComponent} from './user-list';
import {UserDetailComponent} from './user-detail';
@NgModule({
imports :[
usersRouting
],
declarations : [
UserListComponent,
UserDetailComponent
],
providers: []
})
export class UsersModule{}
// main-board.routes
import { RouterModule,Routes } from '@angular/router';
import { MainBoardComponent } from './main-board.component';
const MainBoardRoutes: Routes = [{
path: 'app',
component: MainBoardComponent
}];
export const MainBoardRouting = RouterModule.forChild(MainBoardRoutes);
// users route
import { Routes, RouterModule } from '@angular/router';
import { UserListComponent } from './user-list';
import { UserDetailComponent } from './user-detail';
export const usersRoutes: Routes = [
{path: '', redirectTo: 'app/users', pathMatch:'full'},
{ path: 'users', component: UserListComponent },
{ path: 'user/:id', component: UserDetailComponent }
];
export const usersRouting = RouterModule.forChild(usersRoutes);
Is my approach right to have child NgModule with their own routings or do I have to change them to simple component and have all the routes in main-board
Module routes?
Your methodology is correct. In this approach one needs to import only childmodule into parentmodule, that's it. Childmodule will take care of it's own routing. Similarly if you have nested modules, only modules need to be imported in parent routes rather than declaring lot of routes in one place.
Your approach is right. You want to split the routes to their own sub-modules. Technically you can move the routes to any module as they are merged but it will probably be a bad idea in the long term.
Plunker with resulting routes https://plnkr.co/edit/Y9ReEwnBZNId48xX1CDR?p=preview
@Component({
selector: 'users',
template: `
<div>
<h2>Users</h2>
<ul><li *ngFor="let user of users">{{user}}</li></ul>
</div>
`,
})
export class Users {
users = ["John", "Joe"];
}
const usersRoutes = [
{path: 'users', component: Users}
];
const UsersRoutes = RouterModule.forChild(usersRoutes);
@NgModule({
imports: [ CommonModule, UsersRoutes ],
declarations: [ Users ],
exports: [ Users ]
})
export class UsersModule {}
As said before from others, but I would like to be a little bit clear. Using sub-Module to divide application features is very good, as the application grows they permit to keep a simple code structure.
The best way to manage this process is to have a folders structure like this:
src
- featureA
- featureA.routes.ts
- fefatureA.module.ts
- component1
- component1.ts
- [...]
- component2
- component2.ts
- [...]
- [...]
- featureB
- featureB.routes.ts
- fefatureB.module.ts
- component1
- component1.ts
- [...]
- component2
- component2.ts
- [...]
- [...]
- [...]
- app-routing.module.ts
- app.module.ts
In every feature's module you declare the routes for this particoular module: file feature.routes.ts:
const routerConfig: Routes = [
{
path: '',
component: Component1
},
{
path: 'other',
component: Component2
}
]
and they you import this routes in your feature's module file feature.module.ts:
import { routerConfig } from "./feature.routes";
@NgModule({
imports: [
RouterModule.forChild(routerConfig),
],
})
export class FeatureModule{}
The last thing to do is to import all the stuff in your routing module, lazy loading is perfect for the performace of a tipical application.
file app-routing.module.ts:
import { FeatureAModule } from './featureA/featureA.module';
import { FeatureBModule } from './featureB/featureB.module';
@NgModule({
imports: [
RouterModule.forRoot([
{ path: '', loadChildren: ()=> require("./featureA/featureA.module")["FeatureAModule"]},
{ path: 'feature-b', loadChildren: ()=> require("./featureB/featureB.module")["FeatureBModule"]},
],
{ preloadingStrategy: PreloadAllModules}) //Define the loading strategy
],
})
export class AppRoutingModule {}
And finnaly importing the routing module into your app module file app.module.ts:
import { AppRoutingModule } from './app-routing.module';
@NgModule({
imports: [
AppRoutingModule,
],
})
export class AppModule {}
You need to use the loadChildren property in the route definition, instead of the children in the routers, then point to the child module ( either as a string delimited by a "#", or as a function returning the module )
your approach is right you should divide your routing specific to the module like user module related routing goes in user module it will be very help full as the size of application grows now i think you should try these modification .
//main-board routes file
import { RouterModule,Routes } from '@angular/router';
import { MainBoardComponent } from './main-board.component';
const MainBoardRoutes: Routes = [{
path: 'app',
component: MainBoardComponent
}];
export const MainBoardRouting =
RouterModule.forRoot(MainBoardRoutes); // use for root instead of for child
What you need is loadChildren
child.module.ts
const childRoutes: Routes = [
{
path: '',
component: ChildComponentA
},
{
path: 'other',
component: ChildComponentB
}
]
@NgModule({
imports: [
RouterModule.forChild(childRoutes)
]
})
class MyChildModule {}
app.module.ts
const appRoutes: Routes = [
{
path: 'children',
// If using a function that returns the Module,
// it will be "eager-loaded"
loadChildren: () => MyChildModule
// When using a string, it will be lazy-loaded
// loadChildren: './path/to/child.module#MyChildModule'
}
]
@NgModule({
imports: [
RouterModule.forRoot(appRoutes)
]
})
class AppModule {
}
hi below i have given a sample routing module for app.module and feature module.
app-routing module routing file contains the primary routes and feature module routing file contains the rooting for child roots. hope this helps the resulting roure is /feature/books
app-routing.module.ts //import this in app.module.ts
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
export const routes: Routes = [
{ path: 'feature', loadChildren: 'app/feature/feature.module#FeatureModule'},
{ path: '', redirectTo: 'feature', pathMatch: 'full' },
];
@NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule {
}
feature-routing.module.ts //import this in feature.module.ts
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
// ---- components imported----
import { BooksComponent } from './books/books.component';
import { FeatureComponent } from './feature.component';
const featureRoutes: Routes = [
{
path: '',
component: FeatureComponent,
children: [
{path: '', redirectTo: 'books', pathMatch: 'full'},
{path: 'books', component: BooksComponent},
{path: '**', redirectTo: 'books', pathMatch: 'full'},
]
}
];
@NgModule({
imports: [
RouterModule.forChild(featureRoutes)
],
exports: [
RouterModule
]
})
export class FeatureRoutingModule {
}
I have done this in my recent project. Here is the sample
app.routing.ts
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
RouterModule.forRoot([
{ path: '', loadChildren: '../home/home.module#HomeModule' },
{ path: 'settings', loadChildren: '../settings/settings.module#SettingsModule' },
{ path: 'home', redirectTo: '', pathMatch: 'full' }
])
],
exports: [
RouterModule
]
})
export class AppRoutingModule {
}
home.module.ts
//all necessary imports
@NgModule({
imports: [
CommonModule,
TranslateModule,
FormsModule,
RouterModule.forChild([
{
path: '', component: HomeComponent, canActivate: [SecureGuard]
}
]),
ViewCountPipeModule
],
declarations: [
HomeComponent
],
providers: [
SecureGuard,
CommonService
]
})
export class HomeModule {
}
settings.module.ts
//all the necessary imports
@NgModule({
imports: [
CommonModule,
TranslateModule,
FormsModule,
RouterModule.forChild([
{
path: '', component: RouteHolderComponent,
children: [
{ path: '', redirectTo: 'settings', pathMatch: 'full' },
{ path: 'settings', component: SettingsComponent },
{ path: 'profile', loadChildren: '../profile-settings/profile-settings.module#ProfileSettingsModule' },
{ path: 'account', loadChildren: '../account-settings/account-settings.module#AccountSettingsModule' }
], canActivate: [SecureGuard]
}
]),
RouteHolderModule
],
declarations: [
SettingsComponent
],
providers: [
SecureGuard, SettingsService
]
})
export class SettingsModule {
}
RouteHolderModule
exports RouteHolderComponent
which just has a <router-outlet></router-outlet>
tag in it.