13

In my application I have a SupportModule which has 3 sub-Modules (AdminModule,ChatModule,ContactModule). SupportModule and its 3 sub-Modules have their own routings define.

Structure looks something like

enter image description here

The routing for the `AdminModule' is given below:

import { AdminComponent }   from './admin.component';
import { RssFeedsComponent }   from './rssFeeds.component';
import { RssFeedDetailComponent }   from './rssFeedDetail.component';

export const adminRoutes: Route =      
    {
        path: 'admin',
        component: AdminComponent,
        children: [
            { path: '',  component: RssFeedsComponent },
            { path: 'feeds',  component: RssFeedsComponent },
            { path: 'feeddetail', component: RssFeedDetailComponent }
        ]
    };    

and routing for SupportModule (which is parent module of the 3 sub modules) is given below:

import { SupportComponent } from './support.component';
import { SupportNavComponent } from './support-nav.component';
//Feature Modules
import { chatRoutes } from './chat/chat.routing';
import { contactRoutes } from './contact/contact.routing';
import {adminRoutes} from './admin/admin.routing';

const supportRoutes: Routes = [     
    {
        path: 'support',
        component: SupportComponent,
        children: [
            { path: '',  component: SupportNavComponent },
            chatRoutes,
            contactRoutes,
            adminRoutes
        ]
    }  
];

export const supportRouting: ModuleWithProviders = RouterModule.forChild(supportRoutes);        

Then finally I am importing this supportRouting into my AppModule.

Navigation is working fine without any issue. But I am a little confused. I don't know whether this is the right way to have parent-child modules with their own routing or if there is some better way to achieve this.

If someone can correct me (if I am making a mistake) or knows a better approach then that would be really helpful.

A J Qarshi
  • 2,772
  • 6
  • 37
  • 53

2 Answers2

15

From my reading of the docs, and my own experience with similar routing, what you have done seems to agree with Angular's recommended style.

I just came across this discussion on the Angular github. I haven't tried it yet but it looks like the link provides a better way of doing this.

I'll get back here when I have tried it out.


Following the instructions in the link I first got this working WITH lazy loading – because that's what I really wanted anyway.

I'm not sure which way you are looking for.

With lazy loading it goes like this:

My Hierarchy is

|--App
|    Home
|    Costing
|    |  Payments
|       |   Payments List
|       |   Payments Detail
|    |  Variations
|       | ...
|    Admin
|    |--Projects
|       |...
|    |--Users
|       |...
|  ...

Where Costing, Payments, Variations, Admin, Projects and Users are all modules.

My app.routing then looks like this:

export const appRoutes: Routes =[
  {
    path: '',
    redirectTo: '/home',
    pathMatch: 'full'
  },

  {
    path: 'home',
    component: HomeComponent
  },

  { path: 'costing', loadChildren: 'app/costing/costing.module#CostingModule' },

  { path: 'admin', loadChildren: 'app/admin/admin.module#AdminModule' },

];

export const appRoutingProviders: any[] = [
  authProviders,
];

export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);

costing.routing is:

const routes: Routes = [

  {
    path: '', component: CostingComponent,
    children: [

     { path: '', component: EmptyComponent, pathMatch: 'full' },
     { path: 'payments', loadChildren: 'app/costing/payments/payments.module#PaymentsModule' },
     { path: 'variations', loadChildren: 'app/costing/variations/variations.module#VaritionsModule' }
    ]
  }
];

export const costingRouting: ModuleWithProviders = RouterModule.forChild(routes);

And finally, payments.routing:

const paymentsRoutes: Routes = [

  {
    path: '',
    component: PaymentsListComponent},
  {
    path: 'detail:id',
    component: PaymentsDetailComponent 
  },

];

export const paymentsRouting: ModuleWithProviders = RouterModule.forChild(paymentsRoutes);

I'm sure you could substitute synchronous loading for my lazy loading.

Chris Curnow
  • 643
  • 5
  • 15
  • The discussion link seems to be very helpful. I will look into it but please do share your findings here – A J Qarshi Sep 27 '16 at 10:42
  • Thanks Chris. I am also after lazy loading. Your example is very helpful – A J Qarshi Sep 28 '16 at 15:18
  • @ChrisCurnow correct me if I am wrong, but if you do not lazy load the sub modules in costing-routing.module and use eager loading instead it would be difficult to follow the childRoutes approach such as... costing.module & costing-routing.module, payments.module & payments-routing.module. If you import Payments-Routing.module into Payments.module and then import Payments.module into Costing.module won't you have route interference where the payment routes will not be placed as children in the Costing routes? Can you show an example of how you would follow this same pattern with eager loading? – Blake Rivell Aug 14 '18 at 19:15
  • Hello, this may seem a bit silly however I do not see why you have empty path set for each routing file? – L1ghtk3ira Jan 14 '19 at 20:21
  • I use the empty path as the default path. That means I can just route to the level one above where I want to be and it will route to where I want to be. For example, if I navigate to the payments module, the routing file for that module will route me to the payments list. Therefore I don't have to hard code paymentsList and can just change the default in the routing file. – Chris Curnow Jan 16 '19 at 08:47
9

I guess its really up to you how you want it to be. When ngModules came out, I decided to modularize everything to keep it together. I have a large app with numerous routes. I have placed all main routes to feature modules in the app.routing as such:

import { Routes } from '@angular/router';
import { AuthGuardService } from './services/authGuard.service';

export const appRoutes: Routes = [
    { path: '', redirectTo: '/home', pathMatch: 'full'  },
    { path: 'home',  loadChildren: './app/home/home.module#HomeModule' },
    { path: 'documents',  loadChildren: './app/documents/documents.module#DocumentsModule' },
    { path: 'calculator', loadChildren: './app/calculator/calculator.module#CalculatorModule'},
    { path: 'food',  loadChildren: './app/food/food.module#FoodModule'}, //canActivate: [ AuthGuardService ] },
    { path: 'themes',  loadChildren: './app/themes/themes.module#ThemesModule', canActivate: [ AuthGuardService ] },
    { path: 'settings',  loadChildren: './app/settings/settings.module#SettingsModule', canActivate: [ AuthGuardService ] },
    { path: 'about',  loadChildren: './app/about/about.module#AboutModule' }

];

export const appRoutingProviders: any[] = [];

Then in each feature module I do this, for example: home.routing.ts:

export const routing = RouterModule.forChild([
  { path: 'home', component: HomeComponent },
  { path: 'login', component: LoginComponent },
  { path: 'register', component: RegisterComponent },
  { path: 'verify', component: VerifyComponent },
  { path: 'challenge', component: ChallengeComponent },
  { path: 'verifyEmail/:id', component: VerifyEmailComponent },
  { path: 'change', component: ChangeComponent },
  { path: 'forgot/:id', component: ForgotComponent },
  { path: 'verifyPassword/:id', component: ForgotVerifyComponent },
  { path: 'verifyUserName/:id', component: ForgotVerifyComponent }
]);

I do this with each feature module and I have no trouble with routing and it keeps it modular.

John Baird
  • 2,606
  • 1
  • 14
  • 33
  • 1
    I agree with you proposed structure. I think it is very flexible and keeps isolation between modules which is important for large projects. – Pierre Dec 13 '16 at 18:54
  • @JohnBaird have you ever had to go a level further with nested feature modules? Such as Admin/Users. Admin being equivalent to your Home module and then instead of just having a bunch of components creating another feature module called Users (which will have User-List and User-Detail componenets). I believe it is much easier when you lazy load the sub modules, because if you don't I don't think there is anyway for the routing files of the sub modules to work as children. Correct me if I am wrong. Just wanted to see your thoughts on it. Because I have been struggling to implement it. – Blake Rivell Aug 14 '18 at 19:20