Check out how to build a side navigation that fits perfectly into an admin layout or any dashboard page. We are going to create a simple collapsible sidenav that can be easily integrated into any Angular project that uses Bootstrap.
Our goal is to create a collapsible sidenav. We want it to be hidden by default on smaller screens. You can see the component on the screenshot below:
The final project directory tree:
I try to keep the project up to date. Visit the releases list to keep track of the current versions of frameworks and libraries used. |
$ ng --version Angular CLI: 6.0.8 Node: 8.11.3 OS: linux x64 Angular: 6.1.1
Generate the service for handling the menu toggle action:
$ ng generate service layout/authorised/services/authorised-side-nav
The service function is simple, it has a single parameter – hideSideNav
– and changes its state every time the function toggleSideNav()
is called. See the following code:
// src/app/layout/authorised/services/authorised-side-nav-service.ts import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthorisedSideNavService { hideSideNav: boolean = false; constructor() { } toggleSideNav(): void { this.hideSideNav = !this.hideSideNav; } }
Let’s start with the top bar to create an elegant and functional frame for our dashboard:
$ ng generate component layout/authorised/authorised-top-nav
Replace the default content of the view with the following code:
<!-- src/app/layout/authorised/authorised-top-nav/authorised-top-nav.component.html --> <nav class="navbar navbar-dark bg-dark"> <app-authorised-side-nav-toggler></app-authorised-side-nav-toggler> <h3>keep_growing</h3> </nav>
I’m including here the <app-authorised-side-nav-toggler>
component so we need to add it to the project as well:
$ ng generate component layout/authorised/authorised-side-nav-toggler
And put this code in the template:
<!-- src/app/layout/authorised/authorised-side-nav-toggler/authorised-side-nav-toggler.component.html --> <button type="button" class="navbar-toggler" (click)="sideNavService.toggleSideNav()"> <span class="navbar-toggler-icon"></span> </button>
The toggler requires the AuthorisedSideNavService
so we need to import it and inject to the component constructor:
// src/app/layout/authorised/authorised-side-nav-toggler/authorised-side-nav-toggler.component.ts import { Component, OnInit } from '@angular/core'; import { AuthorisedSideNavService } from '../services/authorised-side-nav.service'; @Component({ selector: 'app-authorised-side-nav-toggler', templateUrl: './authorised-side-nav-toggler.component.html', styleUrls: ['./authorised-side-nav-toggler.component.scss'] }) export class AuthorisedSideNavTogglerComponent implements OnInit { constructor(public sideNavService: AuthorisedSideNavService) { } ngOnInit() { } }
To add those new components to the dashboard we need to include the top bar in our layout:
<!-- src/app/layout/authorised/authorised-layout/authorised-layout.component.html --> <app-authorised-top-nav></app-authorised-top-nav> <div class="wrapper"> <app-authorised-side-nav></app-authorised-side-nav> <app-page-content></app-page-content> </div>
Create the sidebar:
$ ng generate component layout/authorised/authorised-side-nav
The navigation also requires the AuthorisedSideNavService
:
// src/app/layout/authorised/authorised-side-nav/authorised-side-nav.component.ts import { Component, OnInit } from '@angular/core'; import { AuthorisedSideNavService } from '../services/authorised-side-nav.service'; @Component({ selector: 'app-authorised-side-nav', templateUrl: './authorised-side-nav.component.html', styleUrls: ['./authorised-side-nav.component.scss'] }) export class AuthorisedSideNavComponent implements OnInit { constructor(public sideNavService: AuthorisedSideNavService) { } ngOnInit() { } }
In the following code of the component template you can see how we are managing the visibility of the menu only by adding a conditional class to the template – the 'hidden'
class:
<!-- src/main/angular/src/app/layout/authorised/authorised-side-nav/authorised-side-nav.component.html --> <nav id="sidebar" class="navbar-dark bg-dark" [ngClass]="{'hidden': sideNavService.hideSideNav }"> <ul class="navbar-nav"> <li class="nav-item active"> <a class="nav-link" href="#">Home page</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Link</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Link</a> </li> </ul> </nav>
Add the following styling rules:
// src/app/layout/authorised/authorised-side-nav/authorised-side-nav.component.scss :host { background: #343a40; } #sidebar { min-width: 200px; max-width: 200px; min-height: 100vh; color: #fff; transition: all 0.3s; font-weight: 300; font-size: 1rem; line-height: 1.5; } #sidebar.hidden { margin-left: -200px; } a[data-toggle="collapse"] { position: relative; } @media (max-width: 575px) { #sidebar { margin-left: -200px; } #sidebar.hidden { margin-left: 0; } } a, a:hover, a:focus { color: inherit; } #sidebar .sidebar-header { padding: 20px; } #sidebar ul li a { padding: 15px; display: block; width: 100%; &:hover { background-color: rgba(255, 255, 255, 0.1); } } hr { border-top: 1px solid #fff; margin-top: 0; }
On a smaller screen the sidenav is hidden by default, you can still toggle its visibility by clicking the button on the top nav:
The work done in this section is contained in the commit 9300c12c207ba6f53eddbe2424a6aa33b8d629f7.
Remember to include @Component
in tests for components that contain other element:
//src/app/layout/authorised/authorised-top-nav/authorised-top-nav.component.spec.ts … import { Component } from '@angular/core'; @Component({selector: 'app-authorised-side-nav-toggler', template: ''}) class AuthorisedSideNavTogglerComponent {} … TestBed.configureTestingModule({ declarations: [ AuthorisedTopNavComponent, AuthorisedSideNavTogglerComponent ] …
// src/app/layout/authorised/authorised-layout/authorised-layout.component.spec.ts … @Component({selector: 'app-authorised-top-nav', template: ''}) class AuthorisedTopNavComponent {} … beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ AuthorisedLayoutComponent, AuthorisedSideNavComponent, AuthorisedTopNavComponent, PageContentComponent ]
The work done in this section is contained in the commit abd35eaeb9f689c5a84d3964c18bad789f57f43a.
Photo by Alice Moore on StockSnap
Spring Security allows us to use role-based control to restrict access to API resources. However,…
A custom annotation in Spring Boot tests is an easy and flexible way to provide…
Delegating user management to Keycloak allows us to better focus on meeting the business needs…
Swagger offers various methods to authorize requests to our Keycloak secured API. I'll show you…
Configuring our Spring Boot API to use Keycloak as an authentication and authorization server can…
Keycloak provides simple integration with Spring applications. As a result, we can easily configure our…
View Comments
Very Nice Post
Excellent! Simple and concise. Very useful. Thank you very much.
Excellent! Can you help me to understand how can we keep sidebar at right instead of left?
Excellent. Thank you.