Green Grasso Holm
Green Grasso Holm

Reputation: 704

Angular loadChildren isn't doing anything

I'm following along with a course on Angular Fundamentals on PluralSight, creating an event management site with a user module and an events module. (The course doesn't put the events management into a features module, but I did that on my own.) I followed the instructions for letting each module handle its own routing, using loadChildren in the top-level routing:

app.routes.ts

import { Routes } from '@angular/router';
import { NotFoundComponent } from './utility/not-found.component';

export const appRoutes: Routes = [
  { 
      path: 'events', 
      loadChildren: './events/events.module#EventsModule'
  },
  { path: 'user', loadChildren: './user/user.module#UserModule'},
  { path: 'NotFound', component: NotFoundComponent },
  { path: '', redirectTo: '/events', pathMatch: 'full' },
  { path: '**', component: NotFoundComponent }
];

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

import { appRoutes } from './app.routes';

import { AppComponent } from './app.component';
import { SharedModule } from './common/shared.module';
import { NavBarComponent } from './nav/navbar.component';
import { EventService } from './events/event.service';
import { ToastrService } from './common/toastr.service';
import { NotFoundComponent } from './utility/not-found.component';
import { UserModule } from './user/user.module';
import { EventsModule } from './events/events.module';


@NgModule({
  declarations: [
    AppComponent,
    NavBarComponent,
    NotFoundComponent
  ],
  imports: [
    BrowserModule,
    SharedModule,
    EventsModule,
    UserModule,
    RouterModule.forRoot(appRoutes)
  ],
  providers: [
    EventService,
    ToastrService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Then, supposedly, if I want /events to display a list of events, /events/create to display the page for entering a new event, and /events/3 to display the details of the event with id = 3, I should have the following. According to the course, corroborated by Angular's own exposition on the subject, I should specify only the subpaths, omitting the "events" segment that was supposedly already accounted for by the app-level routing.

From event.routes.ts

export const eventRoutes: Routes = [
    { path: 'create', component: CreateEventComponent, canDeactivate: [UnsavedNewEventGuard] },
    { path: ':id', component: EventDetailsComponent, canActivate: [ValidEventGuard] },
    { path: '', component: EventsListComponent }
];

events.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { eventRoutes } from './event.routes';
import { EventsListComponent } from './event-list/events-list.component';
import { CreateEventComponent } from './create-event/create-event.component';
import { EventThumbnailComponent } from './event-list/event-thumbnail.component';
import { EventDetailsComponent } from './event-details/event-details.component';

@NgModule({
  declarations: [
    EventsListComponent,
    CreateEventComponent,
    EventThumbnailComponent,
    EventDetailsComponent,
  ],
  imports: [
    CommonModule,
    RouterModule.forChild(eventRoutes)
  ]
})
export class EventsModule { }

This doesn't work. Instead, it displays the event list directly for the path / (i.e., https://localhost:4200/, which doesn't redirect). It won't route to /events, /events/create, or /events/3.

When I provide the full path, including the "events" segment that I thought I wasn't supposed to need, then the app works:

event.routes.ts (version 2)

export const eventRoutes: Routes = [
    { path: 'events/create', component: CreateEventComponent, canDeactivate: [UnsavedNewEventGuard] },
    { path: 'events/:id', component: EventDetailsComponent, canActivate: [ValidEventGuard] },
    { path: 'events', component: EventsListComponent }
];

Alternatively, nesting the subpaths into a children property under a parent path for "events" also works:

event.routes.ts (version 3)

export const eventRoutes: Routes = [{
  path: 'events', children: [
    { path: 'create', component: CreateEventComponent, canDeactivate: [UnsavedNewEventGuard] },
    { path: ':id', component: EventDetailsComponent, canActivate: [ValidEventGuard] },
    { path: '', component: EventsListComponent }
  ]
}];

But versions 2 and 3 work whether or not I have the routes with the loadChildren attribute in my application-level routing file. The application is quite happy with this:

app.routes.ts (version 2)

import { Routes } from '@angular/router';
import { NotFoundComponent } from './utility/not-found.component';

export const appRoutes: Routes = [
  { path: 'NotFound', component: NotFoundComponent },
  { path: '', redirectTo: '/events', pathMatch: 'full' },
  { path: '**', component: NotFoundComponent }
];

Basically, the loadChildren routes are being ignored. (The same all applies for the user module.) I can't figure out why.

Upvotes: 1

Views: 2449

Answers (1)

penleychan
penleychan

Reputation: 5470

You are importing the module on your app.module.ts. Reason why your "version 2 and 3" works because the modules is imported in your AppModule. To get lazy loading to work you need to remove EventsModule and UserModule from your AppModule:

@NgModule({
  declarations: [...],
  imports: [
    BrowserModule,
    SharedModule,
    RouterModule.forRoot(appRoutes)
  ],
  providers: [...],
  bootstrap: [AppComponent]
})
export class AppModule { }

Also you may need to re-run ng serve after adding new modules for lazy loading.

Upvotes: 2

Related Questions