In this tutorial, we’re gonna look at way to add/remove Route dynamically displaying with Navigation Bar.
Example Overview
Our App has a Navbar that shows Home and Login page at the beginning:
Right after logging in as a User or an Admin, the Navbar changes:
– remove Login page
– add User Board/Admin Board page
– add Logout button
Clicking on Logout button will change the Navbar to the beginning UI:
How to add/remove Route dynamically
Define Route
We define static Routes that will be display all the time. In this example, it’s the Route for Home page.
app-routing.module.ts
const routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', component: HomeComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Configure Components for dynamic Routes
Routes to LoginComponent
, AdminComponent
and UserComponent
will be dynamically add/remove into Navbar, so we define in entryComponents
list so that these Components can be dynamically loaded into the view.
app.module.ts
import { AppRoutingModule } from './app-routing.module'; @NgModule({ declarations: [ ... ], imports: [ ... AppRoutingModule ], entryComponents: [ LoginComponent, UserComponent, AdminComponent ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Add dynamic Routes
For Dynamic Routes that haven’t been defined in app-routing.module.ts, we add Route with necessary data ({path,component}
) to config
array using unshift()
method (or push()
method for the end of the Route[]
array):
constructor(private router: Router) { this.router.config.unshift( { path: 'login', component: LoginComponent }, { path: 'user', component: UserComponent }, { path: 'admin', component: AdminComponent }, ); }
We need a list of available links to be modified in the future, so we declare an Array:
links: Array<{ text: string, path: string }>;
Then show the links
Array on the template:
Add/Remove Route dynamically
Now our work is simple. We just add/remove link to the links Array that we have created before:
// add new link this.links.push({ text: 'Admin Board', path: 'admin' }); // remove existent link this.links.forEach((link, index) => { if (link.text === 'Admin Board') { this.links.splice(index, 1); } });
Practice
Project Structure
– define Routes
in app-routing.module.ts
– 4 page Components for Routes: home, login, user, admin
– implement a service for manage Navbar items(links) and login status in navbar.service.ts
– config page Components for Routes in app.module.ts
– app.component.ts initializes dynamic Routes and app.component.html contains template for displaying dynamic Navbar.
Setup Project
– Create Angular Project:
ng new AngularDynamicRoutes
– Generate Page Components:
ng g c home
ng g c login
ng g c admin
ng g c user
Define Routes
app-routing.module.ts
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home/home.component'; const routes: Routes = [ { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: 'home', component: HomeComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Config Components for dynamic Routes
app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { HomeComponent } from './home/home.component'; import { UserComponent } from './user/user.component'; import { AdminComponent } from './admin/admin.component'; import { LoginComponent } from './login/login.component'; @NgModule({ declarations: [ AppComponent, HomeComponent, UserComponent, AdminComponent, LoginComponent ], imports: [ BrowserModule, AppRoutingModule ], entryComponents: [ LoginComponent, UserComponent, AdminComponent ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Run command: ng g s services/navbar
.
navbar.service.ts
import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class NavbarService { private links = new Array<{ text: string, path: string }>(); private isLoggedIn = new Subject(); constructor() { this.addItem({ text: 'Login', path: 'login' }); this.isLoggedIn.next(false); } getLinks() { return this.links; } getLoginStatus() { return this.isLoggedIn; } updateLoginStatus(status: boolean) { this.isLoggedIn.next(status); if (!status) { this.clearAllItems(); this.addItem({ text: 'Login', path: 'login' }); } } updateNavAfterAuth(role: string): void { this.removeItem({ text: 'Login' }); if (role === 'user') { this.addItem({ text: 'User Board', path: 'user' }); } else if (role === 'admin') { this.addItem({ text: 'Admin Board', path: 'admin' }); } } addItem({ text, path }) { this.links.push({ text: text, path: path }); } removeItem({ text }) { this.links.forEach((link, index) => { if (link.text === text) { this.links.splice(index, 1); } }); } clearAllItems() { this.links.length = 0; } }
app.component.ts
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { UserComponent } from './user/user.component'; import { AdminComponent } from './admin/admin.component'; import { LoginComponent } from './login/login.component'; import { NavbarService } from './services/navbar.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { links: Array<{ text: string, path: string }>; isLoggedIn = false; constructor(private router: Router, private navbarService: NavbarService) { this.router.config.unshift( { path: 'login', component: LoginComponent }, { path: 'user', component: UserComponent }, { path: 'admin', component: AdminComponent }, ); } ngOnInit() { this.links = this.navbarService.getLinks(); this.navbarService.getLoginStatus().subscribe(status => this.isLoggedIn = status); } logout() { this.navbarService.updateLoginStatus(false); this.router.navigate(['home']); } }
app.component.html
Login Components
login.component.ts
import { Component, OnInit } from '@angular/core'; import { NavbarService } from '../services/navbar.service'; @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit { isLoggedIn = false; role = ''; constructor(private navbarService: NavbarService) { this.navbarService.getLoginStatus().subscribe(status => this.isLoggedIn = status); } ngOnInit() { } loginUser() { this.navbarService.updateNavAfterAuth('user'); this.navbarService.updateLoginStatus(true); this.role = 'user'; } loginAdmin() { this.navbarService.updateNavAfterAuth('admin'); this.navbarService.updateLoginStatus(true); this.role = 'admin'; } }
login.component.html
Logged in as {{role}}.
Don't have an account?
Sign Up
I don’t understand why you need dynamic routing for this? Can’t you just hide/unhide whatever menu items you need based on login status?
Your components aren’t dynamic, you may as well declare them all in your app routing module?
Can you show an example which dynamically loads ‘About’, ‘Privacy’, ‘Terms’ page content e.g. from a database, using the same component?
Hi, you can simply do this with
*ngIf
🙂 , the example is in this tutorial:Angular Spring Boot JWT Authentication example | Angular 6 + Spring Security + MySQL Full Stack – Part 3: Build Frontend
this is the thing i was looking for so long . Thankyou
Muchas gracias. ?Como puedo iniciar sesion?