Angular route guards beginners tutorial

Angular route guards beginners tutorial

In this tutorial, we are going to learn about two different types of route guards in the angular router with the help of examples.

Route guards

Route guards help us to prevent access from the particular routes in our app and also prevent the users from the accidental closing of the app.

CanActivate Guard

CanActivate guard is used to protect the routes so that only login users can only access those routes.

In this example, we are creating a login service and auth guard.

Note: You need to clone this repositiory to continue.

Once you successfully cloned the above repository now create a new file called login.service.ts file inside your app folder.

Now add the below code to login.service.ts file.

login.service.ts
import { Injectable } from '@angular/core';

@Injectable({
    providedIn: 'root'})

export  class LoginService {

    isLoggedin = false;
    login() {        this.isLoggedin = true;
    }

    logout() {        this.isLoggedin = false;
    }
}

In the above code, we have created a LoginService class with two methods which are used to change the isLoggedin property value to true or false.

@Injectable decorator helps us to inject this LoginService instance at the root level of our app.

Now create a new file called auth.guard.ts inside your app folder and add the below code.

auth.guard.ts
import {    CanActivate, ActivatedRouteSnapshot,    RouterStateSnapshot} from '@angular/router';import { Injectable } from '@angular/core';
import { LoginService } from './login.service';

@Injectable({
    providedIn: 'root'
})

export class AuthGuard implements CanActivate {

    constructor(private loginservice: LoginService) { }

    canActivate(route: ActivatedRouteSnapshot,state: RouterStateSnapshot):
     boolean
     {
        if (this.loginservice.isLoggedin) {
            // if we return true user is allowed to access that route
            return true;
        } else {
            // if we return false user is not allowed to access
            return false;
        }
    }

}

In the above code, first we imported CanActivate, ActivatedRouteSnapshot,RouterStateSnapshot from the ‘@angular/router’ package and also we imported LoginService we just created it above.

Inside AuthGuard class constructor we injected loginservice and implemented canActivate method.

The canActivate method accepts two parameters which are ActivatedRouteSnapshot and RouterStateSnapshot

If canActivate method returns true we allowing a user to access that route otherwise we denying the access.

Using CanActivate guard

Now we need to choose which routes we need to protect in our app and add the canActivate property to that route bypassing AuthGuard we just created.

The app we cloned from GitHub contains users route, we are protecting this route now.

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { UsersComponent } from './users/users.component';
import { ContactComponent } from './contact/contact.component';
import { NotfoundComponent } from './notfound/notfound.component';
import { UserinfoComponent } from './userinfo/userinfo.component';
import { AuthGuard } from './auth.guard';
const appRoutes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'users', component: UsersComponent,    canActivate: [AuthGuard],    children: [
      { path: ':id', component: UserinfoComponent }
    ]
  },
  { path: 'contact', component: ContactComponent },
  { path: 'contact-us', redirectTo: 'contact' },
  { path: '**', component: NotfoundComponent }
];


@NgModule({
  declarations: [
    AppComponent,
    UsersComponent,
    ContactComponent,
    HomeComponent,
    NotfoundComponent,
    UserinfoComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(appRoutes)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Now if we try to access the /users route in our app it is not opening because by default isLoggedin property present inside LoginService is false.

Let’s create a two new buttons Login and Logout inside our HomeComponent which helps us to change isLoggedin property value to true when we click on a Login button and Logout button changes to false.

home.component.html
<p>home page</p>
<button class="btn" (click)="handleLogin()">Login</button><button class="btn" (click)="handleLogout()">Logout</button>
app.component.ts
import { Component, OnInit } from '@angular/core';
import { LoginService } from '../login.service';

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

  constructor(private loginservice: LoginService) { }

  ngOnInit() {
  }

  handleLogin() {
    this.loginservice.login();
  }

  handleLogout() {
    this.loginservice.logout();
  }
}

Here we imported LoginService and injected it to HomeComponent constructor.

Now open your app in your browser and click on Login button to access the users route.

login-button

users-page

CanActivateChild guard

canActivateChild guard helps us to protect the child routes in our app.

In our current app, we have child routes inside users route so that now we are creating a CanActivateChild method inside auth.guard.ts to protect child routes.

auth.guard.ts
import {
    CanActivate, ActivatedRouteSnapshot,
    RouterStateSnapshot,
    CanActivateChild} from '@angular/router';
import { Injectable } from '@angular/core';
import { LoginService } from './login.service';

@Injectable({
    providedIn: 'root'
})



export class AuthGuard implements CanActivate, CanActivateChild {

    constructor(private loginservice: LoginService) { }

    canActivate(
        route: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): boolean {
        if (this.loginservice.isLoggedin) {
            // if we return true user is allowed to access that route
            return true;
        } else {
            // if we return false user is not allowed to access
            return false;
        }
    }

    canActivateChild(        route: ActivatedRouteSnapshot,        state: RouterStateSnapshot): boolean {            //invoking the canActivate by passing route and state        return this.canActivate(route, state);    }
}

In the above code, we are invoking the canActivate method inside canActivateChild by passing route and state because we have the logic already inside canActivate method.

Using CanActivate child guard

Now we need to update our appRoutes array by passing a new property called canActivateChild

app.module.ts
const appRoutes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'users', component: UsersComponent,
    canActivateChild: [AuthGuard],    children: [
      { path: ':id', component: UserinfoComponent }
    ]
  },
  { path: 'contact', component: ContactComponent },
  { path: 'contact-us', redirectTo: 'contact' },
  { path: '**', component: NotfoundComponent }
];

That’s it, now only loggedin users can access the child routes in our app.

Code repository