Angular 6 dynamic Navigation Bar – add/remove Route dynamically

angular-6-dynamic-navbar-feature-image

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:

angular-6-dynamic-route-add-remove-route-navbar-result-1

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

angular-6-dynamic-route-add-remove-route-navbar-result-2

Clicking on Logout button will change the Navbar to the beginning UI:

angular-6-dynamic-route-add-remove-route-navbar-result-3

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 },
  );
}
Dynamic Navbar

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

angular-6-dynamic-route-add-remove-route-navbar-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 { }
Service for updating Navbar

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;
  }
}
Parent Component displaying Navbar

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

Source Code

AngularDynamicRoutes



By grokonez | October 10, 2018.


Related Posts


5 thoughts on “Angular 6 dynamic Navigation Bar – add/remove Route dynamically”

  1. 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?

Got Something To Say:

Your email address will not be published. Required fields are marked *

*