Actually there is a totally different approach that does not use any of event emitters / listeners. I have nothing against the events and I use both approaches (the below one and @brando's one) according to the particular project needs / complexity.
The method: we have 2 application modules (areas): public (that has no navbar) and protected (the one that has one).
Public module contains all public routes:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { LoginComponent } from './login/login.component';
import { RegistrationComponent } from './registration/registration.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([
{ path: 'login', component: LoginComponent },
{ path: 'registration', component: RegistrationComponent },
{ path: 'reset-password', component: ResetPasswordComponent }
])
],
declarations: [
LoginComponent,
RegistrationComponent,
ResetPasswordComponent
]
})
export class PublicModule { }
This is what you already should have, there is nothing unusual here.
Then we have a protected area
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { NavbarWrapperComponent } from './navbar-wrapper/navbar-wrapper.component';
import { UserProfileComponent } from './user-profile/user-profile.component';
@NgModule({
imports: [
CommonModule,
RouterModule.forChild([
{ path: '', redirectTo: '/login', pathMatch: 'full' }, // point 1
{
path: '', // point 2
component: NavbarWrapperComponent, // point 3
children: [
{ path: 'profile', component: UserProfileComponent }
]
}
])
],
declarations: [
NavbarWrapperComponent,
UserProfileComponent
]
})
export class ProtectedModule { }
and here the magic starts.
First of all, pay attention to the point 1:
{ path: '', redirectTo: '/login', pathMatch: 'full' },
We need this right here. If we put it to the AppModule it will be ignored. There is nothing crucial here, it might be even more logical to have this redirect in the protected module.
Point 2 allows us to proxy all the children routes into the NavbarWrapperComponent
(point 3) which takes care of rendering of all our children. Here is a navbar component's template:
<nav class="navbar navbar-toggleable-md navbar-light bg-faded">
<!-- nav content here -->
</nav>
<router-outlet></router-outlet>
This <router-outlet>
will handle all the children routes.
Possible problems you might face and their solution:
- you might want to put the redirect to the
AppModule
- just change the path in the point 2 to be some real name e.g. protected
. This will prefix all of your protected urls with this value, which you might not want. You have 2 options to choose.
- you might want to have more than just one module inside of the protected area - just use lazy routing
- you might want to hide / show the navigation, pass parameters etc. - just combine it with the events solution.
This way might seem not that flexible, however it really works and covers nearly all the cases you might need. It does not have the events complexity and fully utilises the Router
features. The killer thing here - it is dumb simple and very easy to understand and maintain.