Simple Ionic Tabs App with Child Routes & Protected Routes
Tags: angular, ionic, tutorial, javascript
Published: 2019-07-11 18:47:35

---
title: Simple Ionic Tabs App with Child Routes & Protected Routes
published: true
description: Simple framework in angular for protecting routes in a tab based application using version 4 of Ionic Framework. We also demonstrate handling child routes in a specific Tab
tags: #angular #ionic #tutorial #javascript
cover_image: https://thepracticaldev.s3.amazonaws.com/i/aw0fabp5n55v0z7jya23.png

---

Two question I often see posted about Ionic apps are 
1) how do I handle authentication ( protected routes ) and 
2) How do I handle child routes when using Tabs in Ionic.

So I am going to try to present a simple bare bones solution that addresses both problems with the code I have below. I have only included the code snippets that are essential to address the issues listed above, but the complete source code is available here: [ionicv4-tabs-with-detail](https://github.com/aaronksaunders/ionicv4-tabs-with-detail)

*This example code is based on v4 of Ionic Framework*

##Protected Routes
To have protected routes you need to be able to determine the logged in state of the user. To keep things as simple as possible, we have created an `AuthenticationService` that has a method to set the state as true or false and a method to get the current logged in state.

```javascript
@Injectable({
    providedIn: "root"
})
export class AuthenticationService {
    isLoggedIn = false;

    constructor() { }

    setLoggedIn(_value) {
        this.isLoggedIn = _value;
    }
    isAuthenticated(): boolean {
        return this.isLoggedIn;
    }
}
```
Next we create a new class `AuthGuardService` which implements the [`CanActivate`](https://angular.io/api/router/CanActivate) interface.

In this example, all we are doing is calling the `AuthenticationService` to see if the user is authenticate or not, if the used is not authenticated, then we are redirecting the user to the route defined by the path `/login`. We are doing that by constructing a `UrlTree` object and returning that since we can return a `boolean`, `Promise` or `UrlTree` from the function according to the [`CanActivate` documentation](https://angular.io/api/router/CanActivate)

```javascript
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRoute, Router } from '@angular/router';
import { AuthenticationService } from './authentication.service';

@Injectable({
  providedIn: 'root'
})
export class AuthGuardService implements CanActivate {

  constructor(private auth: AuthenticationService, private router: Router) { }

  canActivate(): boolean {
    let value = this.auth.isAuthenticated()
    if (!value) {
      // initially was just redirecting here, but following the
      // documentation I updated code to return a UrlTree
      // this.router.navigateByUrl("/login", { skipLocationChange: true })

      return this.router.parseUrl("/login");
    }
    return value
  }
}
```
Now that we have our `AuthenticationService` to tell us the state of the user, our `AuthGuardService` to be used to check before rendering a route; we are ready to update the `app-routing.module`.

See below where we add the `AuthGuardService` to the default route so that when the app is first launched, the users authentication state will be verified, otherwise it will redirect to the `LoginPageModule`

```javascript
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthGuardService } from '../services/authGuard.service';

// in the routes that need to be protected or the user
// has to be authenticated, we add the AuthGuardService
const routes: Routes = [
  { 
    path: '', 
    canActivate: [AuthGuardService], 
    loadChildren: './tabs/tabs.module#TabsPageModule' 
  },
  { 
    path: 'login', 
    loadChildren: './public/auth/login/login.module#LoginPageModule' 
  },
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
```

##Child Routes In Tabs
The tabs router module has some magic here to handle the default route and also to properly handle child routes to properly manage the navigation stack for each tab.

The first component rendered is the `TabsPage`, but as you can see that page has child modules, the first one being the `HomePageModule` which will render the `HomePage`.

(1) at the bottom of the code segment below we show how we handle the default route for the tab module, redirecting it to the home tab.

Handling the child route of a tab, or rendering a detail page is demonstrated with the second route definition under the `home` path. We have defined the path `detail` which we access using the full path of `/tabs/home/detail`

(2) This will load the `DetailPageModule` which will in turn load the `DetailPage` since it is the default route in the `DetailPageModule`.


```javascript
const routes: Routes = [
  {
    path: "tabs",
    component: TabsPage,
    children: [
      {
        path: "home",
        children: [
          {
            path: "",
            loadChildren: "./../home/home.module#HomePageModule"
          },
          // (2) loads detail page, pushing it on the navigation stack of 
          // the home tab
          {
            path: "detail",
            loadChildren: "./../detail/detail.module#DetailPageModule"
          }
        ]
      },
      {
        path: "about",
        children: [
          {
            path: "",
            loadChildren: "./../about/about.module#AboutPageModule"
          }
        ]
      },
      {
        path: "contact",
        children: [
          {
            path: "",
            loadChildren: "./../contact/contact.module#ContactPageModule"
          }
        ]
      }
    ]
  },
  // (1) the default route of this module is the home tab so that tab is
  // displayed when directed here from the top level router module.
  {
    path: "",
    redirectTo: "/tabs/home",
    pathMatch: "full"
  }
];
```

##Handling the Routes in the Application
###Log In
For logging in to the application, we have included the following code in the `login.page.ts` file. The application will first call the injected `AuthenticationService` to set the logged in state, and then it will navigate to the default route of the application
```javascript
  login() {
    this.auth.setLoggedIn(true)
    this.router.navigateByUrl("/", { skipLocationChange: true });
  }
```
###Log Out
For logging out of the application, we have included the following code in the `home.page.ts` file. The application will first call the injected `AuthenticationService` to set the logged in state, and then it will navigate to the login route of the application.
```javascript
  logout() {
    this.auth.setLoggedIn(false)
    this.router.navigateByUrl("/login", { skipLocationChange: true });
  }
```
###Detail Page
For navigating the child root from the `HomePage` Tab, we have included the following code in the page; using an `ion-button`
```html
<ion-button routerLink="/tabs/home/detail">Next</ion-button>
```
#Project Source Code
For the sake of brevity, I have not included all of source code this post, but the git hub repo is listed below.
{% github https://github.com/aaronksaunders/ionicv4-tabs-with-detail %}
#Even More...
Here is a similar implementation, but it includes the [sidemenu/splitpane](https://ionicframework.com/docs/api/split-pane) along with the [Tabs](https://ionicframework.com/docs/api/tabs) and authentication
{% github https://github.com/aaronksaunders/ionic4-sidemenu-auth %}