Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent routing in Angular when user manually changes url in browser tab

Tags:

I am stuck in a issue that happens when user manually changes the route in browser tab and presses enter. This forces my ui-router/angular2-router to navigate to the state entered by user. I want to prevent this and allow routing only through the flow I have implemented by button clicks in my website.

like image 417
Peter Avatar asked Mar 29 '16 07:03

Peter


People also ask

How do I change the URL in an Angular application without reloading the route?

Redirect. When this button is clicked, we'll perform the URL change without loading the new route. import { Location } from '@angular/common'; 1import { Location } from '@angular/common';

How does Angular determine routing change?

Steps to detect route change in Angular application Urls. Import Router, Event, NavigationStart, NavigationEnd, NavigationError from '@angular/router'. And inject router in the constructor. Subscribe to the NavigationStart, NavigationEnd, NavigationError events of the router.

What does RouterLink do in Angular?

RouterLink is a built-in Angular Directive that lets you link to specific routes in your app. In the SPA(single-page application), you change what the user sees by showing or hiding portions of the display that correspond to particular components, rather than going out to the server to get a new page.

What is skipLocationChange?

skipLocationChange: boolean. You can change the route, without changing the URL in the browser. This Navigates to a new URL without pushing a new state into history.


2 Answers

Its 2018! Angular 5 is here and so is the solution to this issue. BAMM its CanActivate Interface that a class can implement to be a guard deciding if a route can be activated.

We can add this functionality and prevent the access to some of our routes based on the conditions we define. A service for eg AuthGuard that implements the CanActivate interface and defines the canActivate method can be added to route configuration.

class Permissions {
  canGoToRoute(user: UserToken, id: string): boolean {
    return true;
  }
}

@Injectable()
class AuthGuard implements CanActivate {
  constructor(private permissions: Permissions, private currentUser: UserToken) {}

  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean>|Promise<boolean>|boolean {
    return this.permissions.canGoToRoute(this.currentUser, route.params.id);
  }
}

If we have a route that we want to protect access to against some condition, we add the guard as follows:

const appRoutes: Routes = [
  { path: 'crisis-center', component: CrisisListComponent },
  {
    path: 'heroes',
    canActivate: [AuthGuard],
    component: HeroListComponent,
    data: { title: 'Heroes List' }
  },
  { path: '',
    redirectTo: '/heroes',
    pathMatch: 'full'
  },
  { path: '**', component: PageNotFoundComponent }
];

Here the route heroes and all its children have a layer of guard over it. Hence based on the boolean value returned by the AuthGuard service the user will be allowed or denied access to this route.

like image 145
Peter Avatar answered Sep 28 '22 21:09

Peter


You can import router in the constructor of a guard. This router instance will have the current URL. ActivatedRouteSnapshot and RouterStateSnapshot in canActivate will contain the URL that the user is attempting to access.

The below example prevents users from directly accessing a route from an outside page.

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class DirectAccessGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    // If the previous URL was blank, then the user is directly accessing this page
    if (this.router.url === '/') {
      this.router.navigate(['']); // Navigate away to some other page
      return false;
    }
    return true;
  }
}

Add this guard to your routing module

{ path: 'signup/:type/:step', component: SignupComponent, canActivate: [DirectAccessGuard] }
like image 40
Scott Reed Avatar answered Sep 28 '22 22:09

Scott Reed