Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular.io routing for Login page and Main view (with nested views) using multiple modules/files

Using Angular 4's routing with separate files/modules for my features, I'm trying to make my app always show the login screen first then switch to my main view once the user logs in (all routes are guarded by authentication, except the login one).

I created a test app in Plunker, with notes within the app about the functionality I need, as opposed to what's currently happening: https://plnkr.co/edit/MGIGH4xpKZOtgCBl5lam

The problem I've had with most sample code (like this one) is that the component being routed to after login does not have any nested views. I got my app working by putting all the routes in a single file, but I'd prefer splitting up the routes per feature. However, as soon as I do that, things start getting wonky:

  • Clicking the login button shows the club component, without being nested in the main-nav's template; plus the club component shows even before authentication is done.
  • If I navigate manually by typing 'members' in the url, the member list shows correctly, but when I click on a member, it shows "page not found" instead of the member-detail view

It's close, though -- typing in either "club" or "members" in the url will force the login page to show and when I click the login button, it will then show the correct page, nested in the main-nav view. Then I can use the main-nav links to flip back and forth between "club" and "members" and logout.

I think the problem may be with the way I'm doing the lazy loading, maybe?

const routes: Routes = [
  { path: '', component: MainNavComponent,
    canActivate: [AuthGuard],
    children: [
      { path: 'club', loadChildren: 'app/club.module#ClubModule'},
      { path: 'members', loadChildren: 'app/members.module#MembersModule'},
      { path: '', redirectTo: 'club', pathMatch: 'full' }
    ]
  }
];

I followed the angular.io routing docs and these suggestions to get it working as well as it is, but I can't figure out the last bit that's messed up. I'd really appreciate any help!

like image 444
Sherri M Avatar asked Jun 14 '17 11:06

Sherri M


People also ask

Does Angular support nested routing?

We can nest routes, this means that for a given URL we can render a tree of components. We do this by using multiple router-outlet directives and configuring child routes on our route configuration object.

Can we define multiple router outlets in a component view?

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.

Which mechanism allows the user to navigate between components views?

➔ The routing mechanism allows us to navigate between different views(via components) and allowing us to configure it to make it more flexible while providing us with features like lazy loading to ease load times and increase performance.


1 Answers

There were a variety of issues which I addressed and added to the demo below.

  1. Do not import the lazy loaded modules into the app module as this causes them to be loaded immediately. This also makes the module routes take precedence over the AppModule routes.
@NgModule({
  declarations: [
    AppComponent,
    PageNotFoundComponent
  ],
  imports: [
    BrowserModule,
    AuthModule,
    // ClubModule,
    // MainNavModule,
    // MembersModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  1. The lazy loaded modules should all behave as there own app so the routes should be configured so that the root component of each module has an empty path.
// club-routing.module.ts
const routes: Routes = [
  { path: '',  component: ClubComponent }
];
// members-routing.module.ts
const routes: Routes = [
  {
    path: '',
    component: MembersComponent,
    canActivate: [AuthGuard],
    children: [
      { path: ':id', component: MemberDetailComponent }
    ]
  }
];
  1. Lastly, the app module should have a default path for the router to resolve to. In my example I had it resolve to the routing module since it is protected by a guard but you could just as easily route it to the login module.
// app-routing.module.ts
const routes: Routes = [
  { path: '', loadChildren: 'app/main-nav.module#MainNavModule' },
  { path: 'login', component: LoginComponent },
  { path: '**', component: PageNotFoundComponent }
];

Demo

like image 199
Teddy Sterne Avatar answered Sep 21 '22 12:09

Teddy Sterne