Hide SideNav While Login in Angular Material

author-imageBy Dhiraj, 28 July,2018   0K

In my last article, we looked into creating a SideNav using Angular 6 material designing in a single page application(SPA). But in most of the real time scenario, we require the SideNav to be hidden during login and viewable only after successful login. Being a SPA with routing implemented, sometimes it becomes challenging to do so. Hence, in this article we will be creating a SPA with routing to hide SideNav during login and make it viewable post login.

There are two ways with which we can achieve it. First, the very simple but not standard way is by using ngIf and secondly, we can use multi-layout design with children routes implemented. Here, in this article we will be using second approach.

In this example to keep things simple, we will be creating only 2 layouts but you can create as many layouts as you want. We will define two different layout as login-layout and home-layout component and these component will be our parent routes and remaining all the other routes will be child routes. Apart from this, we can also use angular provided AuthGuards to secure these routes and we will be discussing about AuthGuards in next article.

Building Angular 6 Material App

We have already created many Angular 6 app in my last articles. You can find the complete article of creating Angular 6 App here. Hence, let us just review the CLI command we used to set up Angular 6 project and integrate material designing with it.

ng new angular6-sidenav-example
cd angular6-sidenav-example
ng add @angular/material
ng g c login-layout
ng g c home-layout
ng g c login
ng g c navigation
ng g c first
ng g c second
ng g c toolbar

For a clear implementation, I have created a separate file - material.module.ts and imported in our app.module.ts.

material.module.ts
import {NgModule} from "@angular/core";
import { CommonModule } from '@angular/common';
import { MatButtonModule, MatNativeDateModule, MatIconModule, MatSidenavModule,
  MatListModule, MatToolbarModule, MatCardModule, MatInputModule} from '@angular/material';

@NgModule({
  imports: [CommonModule, MatButtonModule,MatToolbarModule, MatNativeDateModule, MatIconModule, MatSidenavModule, MatListModule, MatCardModule, MatInputModule],
  exports: [CommonModule, MatButtonModule, MatToolbarModule, MatNativeDateModule, MatIconModule, MatSidenavModule, MatListModule, MatCardModule, MatInputModule],
})
export class CustomMaterialModule { }

Below is our final project structure.

angular6-material-hide-sidenav

Multiple layout Routing Configuration

Our main idea to hide SideNav is by creating multiple layouts. In the following routing configuration, we have 2 parent routes configured as login and home. With login we have simply LoginComponent which will be rendered in <router-outlet> and post login main route will be rendered. Inside the main component, we have again 2 child routes. These 2 child routes will be rendered in the main content of SideNav based on the nav item clicked in the side content and the url becomes main/first and main/second.

In the app.comonent.html we have removed all the html elements and only <router-outlet> <router-outlet> is present.

We can also have routeguard configured here but we will be doing that in our next example.

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NavigationComponent } from './navigation/navigation.component';
import { SecondComponent } from './second/second.component';
import { FirstComponent } from './first/first.component';
import {RouterModule, Routes} from "@angular/router";
import {CustomMaterialModule} from "./core/material.module";
import { LoginLayoutComponent } from './login-layout/login-layout.component';
import { HomeLayoutComponent } from './home-layout/home-layout.component';
import { LoginComponent } from './login/login.component';
import { ToolbarComponent } from './toolbar/toolbar.component';

const appRoutes: Routes = [
  { path: '', redirectTo: 'login', data: { title: 'First Component' }, pathMatch: 'full' },
  {
    path: 'login', component: LoginLayoutComponent, data: {title: 'First Component'},
    children: [
      {path: '', component: LoginComponent}
    ]
  },
  { path: 'main', component: HomeLayoutComponent,
    children: [
      { path: '', redirectTo: 'first', pathMatch: 'full' },
      { path: 'first', component: FirstComponent },
      { path: 'second', component: SecondComponent }
    ]
  }
];
@NgModule({
  declarations: [
    AppComponent,
    NavigationComponent,
    SecondComponent,
    FirstComponent,
    LoginLayoutComponent,
    HomeLayoutComponent,
    LoginComponent,
    ToolbarComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    RouterModule.forRoot(
      appRoutes,
      { useHash: false } // <-- debugging purposes only
    ),
    CustomMaterialModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

pathMatch = 'full' results in a route hit when the remaining, unmatched segments of the URL match is the prefix path

pathMatch = 'prefix' tells the router to match the redirect route when the remaining URL begins with the redirect route's prefix path.

Login Component without SideNav

First let us define our html for login-layout.component.ts

login-layout.component.html
<router-outlet></router-outlet>

This will hold the child component in it and while login login.component.html will be rendered inside this login-layout.component.html and this parent route will be rendered inside the app.component.html. Below is our login.component.html

login.component.html
<app-toolbar></app-toolbar>
<mat-card class="example-card">
  <mat-card-header>
    <mat-card-title>Login</mat-card-title>
  </mat-card-header>
  <mat-card-content>
    <form>
      <table class="example-full-width" cellspacing="0">
        <tr>
          <td>
            <mat-form-field class="example-full-width">
              <input matInput placeholder="Username" formControlName="email" name="username" required>
            </mat-form-field>
          </td>
        </tr>
        <tr>
          <td><mat-form-field class="example-full-width">
            <input matInput placeholder="Password" formControlName="password" type="password" name="password" required>
          </mat-form-field></td>
        </tr></table>
    </form>
  </mat-card-content>
  <mat-card-actions>
    <button mat-raised-button color="primary">Login</button>
  </mat-card-actions>
</mat-card>

login.component.html also has directive <app-toolbar></app-toolbar>. With this we can have multiple toolbar component for login and home.

toolbar.component.html
<mat-toolbar color="warn">
  <mat-toolbar-row>
    <span><img src="./assets/devglan.png"></span>
  </mat-toolbar-row>
</mat-toolbar>

With this much configuration, our final login component wil be rendered in the browser as below:

angular6-material-hide-sidenav-during-login

Home Layout with SideNav

Once, the user successfully logs in, we can show our layout that has SideNav in it. Following is our home-layout.component.html

home-layout.component.html
<app-navigation></app-navigation>

Following is our navigation.component.html. This is the same component we created lat time when we were discussing about SideNav in Angular 6 Material in my previous article. You can visit it for complete explanation of Sidenav.

navigation.component.html
<mat-toolbar color="warn">
  <mat-toolbar-row>
    <button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()" color="primary">
      <mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
    </button>
    <span><img src="./assets/devglan.png"></span>
  </mat-toolbar-row>
</mat-toolbar>
<mat-sidenav-container class="example-container">
  <mat-sidenav #drawer mode="side" opened role="navigation">
    <mat-nav-list>
      <a mat-list-item routerLink='first'>First Component</a>
      <a mat-list-item routerLink='second'>Second Component</a>
    </mat-nav-list>
  </mat-sidenav>
  <mat-sidenav-content>
    <router-outlet></router-outlet>
  </mat-sidenav-content>
</mat-sidenav-container>
navigation.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

With this much configuration, we can have our home component with SideNav in it.

angular6-material-show-sidenav-after-login

Conclusion

In this article, we discussed about hiding Angular 6 Material SideNav during login and show it only post login in the home screen. We also looked into how we can have multiple toolbar for login and home page in a SPA. You can check out the source from my github page here.

Further Reading on Angular JS

1. Material Sidenav Example

2. Spring Boot Angular Captcha

3. Rxjs Tutorial

4. Angular Data Table Example

5. Spring Boot Jwt Auth

If You Appreciate What We Do Here On Devglan, You Should Consider: