Handle Back-Forth Page Routing

Hi Friends, This is Lakshman here.

It's been a long time since the last post, But it's good to see you all.

Welcome back to the Series "Angular Best Practices".

Today, We will go through options to navigate between page back-forth page routing on App.

Back-Forth Page Routing

As we develop the application most probably, we will navigate between pages.

The Usually Navigation options might be as below, * Header with All Navigation Option. * From Master to Detail, etc.,

If, our Angular App deployed as the Web Portal. The Navigation options will be the default because you can access only via Menus.

What if, our angular app deployed as Mobile App. User can able to navigate not only via Page Menu and also via default back options.

In this case, most probably, we may use a navigation service to maintain history.

If you navigate a page via Phone's back options, it might cause an issue on the app.

To Address the Issue, I have implemented the Session storage option to capture the Page navigation instead of hard-coded back functionality.

No Await, Code for Common Service to Handle Session Storage create a file under app with name common.service.ts copy paste the below,

export class Common {
  constructor(private source?: string) {}

  //#region Navigation

  SetLocal(Key: string, localContext: any) {
    if (localContext) {
      sessionStorage.setItem(Key, JSON.stringify(localContext));
    } else {
      sessionStorage.removeItem(Key);
    }
  }

  GetLocal(Key: string) {
    const savedLocalData = sessionStorage.getItem(Key);
    let _Value = null;
    if (savedLocalData) {
      _Value = JSON.parse(savedLocalData);
    }
    return _Value;
  }

  NavReset() {
    this.SetLocal('Nav_Url', []);
  }

  NavGetLocal() {
    let rtnUrl: string;

    const savedLocalData = sessionStorage.getItem('Nav_Url');
    let _Value = [];
    if (savedLocalData) {
      _Value = JSON.parse(savedLocalData);
    }

    if (_Value) {
      if (_Value.length > 0) {
        rtnUrl = _Value[_Value.length - 1];
      }
    }

    return rtnUrl;
  }

  NavSetLocal(Url: string) {
    // Includes Home Page URL.  
    if (Url.includes('login') || Url.includes('nonetwork') || Url === '/') {
      return false;
    }

    const savedLocalData = sessionStorage.getItem('Nav_Url');
    let _Value = [];
    if (savedLocalData) {
      _Value = JSON.parse(savedLocalData);
    }

    if (_Value) {
      if (_Value.length > 0) {
        const index = _Value.indexOf(Url, 0);

        if (index !== -1) {
          _Value.splice(index, 1);

          _Value.push(Url);
          this.SetLocal('Nav_Url', _Value);
        } else {
          _Value.push(Url);
          this.SetLocal('Nav_Url', _Value);
        }
      } else {
        _Value.push(Url);
        this.SetLocal('Nav_Url', _Value);
      }
    }
  }

  NavRemoveLocal(Url: string) {
    const savedLocalData = sessionStorage.getItem('Nav_Url');
    let _Value = [];
    if (savedLocalData) {
      _Value = JSON.parse(savedLocalData);
    }

    if (_Value.length > 0) {
      const index = _Value.indexOf(Url, 0);

      if (index !== -1) {
        _Value.splice(index, 1);
      }

      this.SetLocal('Nav_Url', _Value);
    }
  }

  //#endregion

}

Now, its time to add Navigate URL to Session in app.Component.ts as below,

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { merge } from 'rxjs';
import { filter, map, switchMap } from 'rxjs/operators';

import { Common } from './common.service.ts';

const com = new Common('App');

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
  constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute,    
  ) {}

  async ngOnInit() {
    ...
    const onNavigationEnd = this.router.events.pipe(filter((event) => event instanceof NavigationEnd));

    merge(..., onNavigationEnd)
      .pipe(
        map(() => {
          let route = this.activatedRoute;
          while (route.firstChild) {
            route = route.firstChild;
          }
          return route;
        }),
        filter((route) => route.outlet === 'primary'),
        switchMap((route) => route.data),
        untilDestroyed(this)
      )
      .subscribe((event) => {
        com.NavSetLocal(window.location.pathname);
        ...
      });
    
    ...
  }
...
}

To Remove the Previous Navigated URL, if you have Back Option add this code as below,

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { Common } from './common.service.ts';

const com = new Common('Header');

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
})
export class HeaderComponent implements OnInit {
  constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute,    
  ) {}

  ToBack() {    
    com.NavRemoveLocal(window.location.pathname);
    const Url = com.NavGetLocal();

    if (com.IsValid(Url)) {
      this.router.navigateByUrl(Url);
    } else {
      this._location.back();
    }
  }
}

On-road head, we will discuss a lot of things.

Looking forward to your comments and share your feedback.

Until that, I am Lakshman, Signing Off.

Comments

Popular posts from this blog

Model Mapper in Angular

Implement Logging in Angular with Firebase

Dockerize Angular App for Dev