How to detect a route change in Angular?
Asked Answered
O

31

678

I am looking to detect a route change in my AppComponent.

Thereafter I will check the global user token to see if the user is logged in so that I can redirect the user if the user is not logged in.

Operand answered 4/11, 2015 at 10:56 Comment(1)
techiediaries.com/angular-candeactivateLombroso
P
797

In Angular 2 you can subscribe (Rx event) to a Router instance.

So you can do things like:

class MyClass {
  constructor(private router: Router) {
    router.subscribe((val) => /*whatever*/)
  }
}

Since rc.1:

class MyClass {
  constructor(private router: Router) {
    router.changes.subscribe((val) => /*whatever*/)
  }
}

Since 2.0.0:

See also : Router.events doc

class MyClass {
  constructor(private router: Router) {
    router.events.subscribe((val) => {
        // see also 
        console.log(val instanceof NavigationEnd) 
    });
  }
}
Pyonephritis answered 5/11, 2015 at 15:44 Comment(15)
Regarding the deprecated version: For some reason this would not detect the first route change i'm making on initial load. I had to wrap this in a timeout of 400ms in the constructor, or 300ms in ngAfterViewInit, and then it works every time. ...even still, val is empty when using the browser back and forward buttons :(Magel
Does anyone has a plunker example for this? I am having dependency injection error by only injecting Router.Poulenc
Is there a way to get the data in this event I passed in route configuration?Abode
I am able to get data by event._root.children[0].value._routeConfig.data I hope there can be better wayAbode
@Abode have you seen this article by Todd Motto: [Dynamic page titles in Angular 2 with router events] (toddmotto.com/dynamic-page-titles-angular-2-router-events)Vinificator
why does it fire 3 times?Elul
@Elul its because the event has 3 states and in a success change of url. The 3 states are :'NavigationStart', 'NavigationEnd' and 'RoutesRecognized'Dabble
How to I make it fire only once?Lenoir
dont you have to unsubscribe?Grivation
you could check if (val instanceof NavigationStart) to make it fire onceCapful
you can filter the events easily with RxJS filter operator. router.events.pipe(filter(e => e instanceof NavigationEnd).subscribe((e) => { ... }Keciakeck
Perfect, How can I get exact param.id of url ? @PyonephritisCalcine
@Keciakeck iam not sure but i think you forgot a closing bracket before .subscribe(Parmentier
@Parmentier yes. I can’t fix it because it’s a comment. Thx 😊Keciakeck
to get event url I use router.events .pipe(filter((event): event is NavigationEnd => event instanceof NavigationEnd)) .subscribe((event: NavigationEnd) => { console.log(event.url); });Brewery
O
422

RxJS 6

router.events.pipe(filter(event => event instanceof NavigationStart))

Thanks to Peilonrayz (see comments below)

new router >= RC.3

import { Router, NavigationStart, NavigationEnd, NavigationError, NavigationCancel, RoutesRecognized } from '@angular/router';

constructor(router:Router) {
  router.events.forEach((event) => {
    if(event instanceof NavigationStart) {
    }
    // NavigationEnd
    // NavigationCancel
    // NavigationError
    // RoutesRecognized
  });
}

You can also filter by the given event:

import 'rxjs/add/operator/filter';

constructor(router:Router) {
  router.events
    .filter(event => event instanceof NavigationStart)
    .subscribe((event:NavigationStart) => {
      // You only receive NavigationStart events
    });
}

Using the pairwise operator to get the previous and current event also is an nice idea. https://github.com/angular/angular/issues/11268#issuecomment-244601977

import 'rxjs/add/operator/pairwise';
import { Router } from '@angular/router';

export class AppComponent {
    constructor(private router: Router) {
        this.router.events.pairwise().subscribe((event) => {
            console.log(event);
        });
    };
}
Oswell answered 28/6, 2016 at 15:41 Comment(18)
Thank you. How do I update my version of the router with got bash command?Operand
Sorry, I don't know, I only use it from prepared Plunker. Locally I use Dart.Stephine
@GunterZochbauer instead of 'is' I would use 'instanceof'. And 'event: Event' should be in parentheses. Thanks for this, pretty powerful new feature! I like itSubclimax
This does throw a compilation error on the current versions Argument of type '(event: Event) => void' is not assignable to parameter of typePelpel
@RudiStrydom That looks like a mistake in your code. Nothing has changed here since RC.3. Can you please create a new question and add the code that allows to reproduce.Stephine
What would be the appropriate solution to get the component as well(>= RC5)? I want to use the title service to set the document.title when the route changes. The title name I would like to fetch from the component itself or attach it to the route information.Dioptric
@Dioptric please create a new question. That doesn't seem to be related to this question.Stephine
@RudiStrydom & Günter Zöchbauer - the Argument of type '(event: Event) => void' is not assignable to parameter of type error is because in your filter snippet you are subscribing to an object of type Event instead of NavigationEvent.Mcmanus
Is there a way to get the data in this event I passed in route configuration?Abode
Doesn't look like it. You can inject the Router and try to get it from router.routerstate.activatedRoute... or router.routerstate.snapshot... Not sure if it's available there, it's quite some time I checked.Stephine
Second sample should be NavigationEvent instead of Event. Also dont forget to import "Event as NavigationEvent" from @angular/routerCreight
@Creight thanks for the hint. That changed a while back and it seems I missed that when updating. I find the imports a bit redundant. Every type needs to be imported anyway.Stephine
The hint about the import was for anyone looking to solve this error :)Creight
on every route change pairwise is being called thrice any reason @GünterZöchbauer /Nucleolated
in angular 5 -> "property 'filter' does not exist on type 'Observable<event>' "Skidway
Same response as on the other answer. filter is not related to Angular. Observable is RXSJ5 and there still is filterStephine
I just applied router.events.pipe(filter(event => event instanceof NavigationStart)) on AppRoutingModule, now its working fine. Thanks.Rev
You improve your filter statement by making it a typeguard: router.events.pipe(filter((event: Event): event is NavigationEnd => event instanceof NavigationEnd));. See github.com/ReactiveX/rxjs/issues/3125#issuecomment-345557136Benford
M
162

For Angular 7 someone should write like:

this.router.events.subscribe((event: Event) => {})


A detailed example can be as follows:

import { Component } from '@angular/core'; 
import { Router, Event, NavigationStart, NavigationEnd, NavigationError } from '@angular/router';

@Component({
    selector: 'app-root',
    template: `<router-outlet></router-outlet>`
})
export class AppComponent {

    constructor(private router: Router) {

        this.router.events.subscribe((event: Event) => {
            if (event instanceof NavigationStart) {
                // Show loading indicator
            }

            if (event instanceof NavigationEnd) {
                // Hide loading indicator
            }

            if (event instanceof NavigationError) {
                // Hide loading indicator

                // Present error to user
                console.log(event.error);
            }
        });

   }
}
Mcmasters answered 8/11, 2018 at 12:40 Comment(7)
This is great! very comprehensive! worked perfectly on Angular 7.Dolora
Usually the navigation itself takes very little time if you use preloading strategy. In terms of usability I would use loading indicators only on backend http requests, if at all.Gorey
This works perfectly. My requirement is for a particular route->component, listener implement in that particular component only should be triggered. Is there any way I can limit the event listening confined to a component because I have multiple components implementing these listener and all of them get fired when rout changes.Filth
In the constructor, you should not use <this>, your case is for ngOnInit.Nineteenth
Perfect, How can I get exact param.id of url ?Calcine
The solution is not component limited, it spreads throughout the app, consuming resourcesAlexandrine
@SergioReis I don't see any problem using the constructor here. You cannot access/use this if it refers to an @Input(), but here, this.router is injected in the constructor, so perfectly defined...Editheditha
K
91

Angular 7, if you want to subscribe to router

import { Router, NavigationEnd } from '@angular/router';

import { filter } from 'rxjs/operators';

constructor(
  private router: Router
) {
  router.events.pipe(
    filter(event => event instanceof NavigationEnd)  
  ).subscribe((event: NavigationEnd) => {
    console.log(event.url);
  });
}
Kellene answered 8/10, 2018 at 7:47 Comment(2)
it does not capture the redirect eventSocial
@AnandhuAjayakumar Of course yes it works ! the event has two properties url and urlAfterRedirects, in case of a redirect the event has url set to from which path redirection is made and urlAfterRedirects set to path after redirectProteiform
M
53

Angular 4.x and above :

This can be achieved using url property of ActivatedRoute class as below,

this.activatedRoute.url.subscribe(url =>{
     console.log(url);
});

Note: That you need to import and inject the provider from angular/router package

import { ActivatedRoute } from '@angular/router`

and

constructor(private activatedRoute : ActivatedRoute){  }
Mert answered 31/10, 2017 at 7:47 Comment(0)
M
39

In Angular 8 you should do like this.router.events.subscribe((event: Event) => {})

Example:

import { Component } from '@angular/core'; 
import { Router, Event } from '@angular/router';
import { NavigationStart, NavigationError, NavigationEnd } from '@angular/router';

@Component({
    selector: 'app-root',
    template: `<router-outlet></router-outlet>`
})
export class AppComponent {

    constructor(private router: Router) {
        //Router subscriber
        this.router.events.subscribe((event: Event) => {
            if (event instanceof NavigationStart) {
                //do something on start activity
            }

            if (event instanceof NavigationError) {
                // Handle error
                console.error(event.error);
            }

            if (event instanceof NavigationEnd) {
                //do something on end activity
            }
        });
   }
}
Minefield answered 3/3, 2020 at 9:48 Comment(0)
I
20

In angular 6 and RxJS6:

import { filter, debounceTime } from 'rxjs/operators';

 this.router.events.pipe(
      filter((event) => event instanceof NavigationEnd),
      debounceTime(40000)
    ).subscribe(
      x => {
      console.log('val',x);
      this.router.navigate(['/']); /*Redirect to Home*/
}
)
Implicatory answered 15/6, 2018 at 13:12 Comment(1)
you missed import for Router import {Router, NavigationEnd} from "@angular/router"Lieutenant
D
20

In Angular 10, you can do something like the following...

    import { Component, OnInit } from '@angular/core';
    import { Router, NavigationEnd } from '@angular/router';
    import { filter } from 'rxjs/operators';
    
    @Component({
      selector: 'app-my-class',
      templateUrl: './my-class.component.html',
      styleUrls: ['./my-class.component.scss']
    })
    export class MyClassComponent implements OnInit {
      constructor(private router: Router) {}
    
      ngOnInit(): void {
        this.router.events
        .pipe(filter(event => event instanceof NavigationEnd))  
        .subscribe((event: NavigationEnd) => {
          // code goes here...
        });
      }
    }
Disengagement answered 13/10, 2020 at 6:12 Comment(1)
sir i have redirect to another page after subscribe but its redirected ?Hi
K
19

Router 3.0.0-beta.2 should be

this.router.events.subscribe(path => {
  console.log('path = ', path);
});
Knurled answered 6/7, 2016 at 16:52 Comment(1)
that works for current path but what about previous?Skidway
E
18

The answers here are correct for router-deprecated. For the latest version of router:

this.router.changes.forEach(() => {
    // Do whatever in here
});

or

this.router.changes.subscribe(() => {
     // Do whatever in here
});

To see the difference between the two, please check out this SO question.

Edit

For the latest you must do:

this.router.events.subscribe(event: Event => {
    // Handle route change
});
Extension answered 7/5, 2016 at 15:38 Comment(3)
Does it provide any data of previous and current route?Symmetry
The router has been updated again (I haven't updated my answer yet), so I'm not sure how it is for the latest. For the router I wrote about, you couldn't. @SymmetryExtension
Please could you provide some context for this answer? which lines are you replacing in the other solutions with yours?Sewell
I
13

After spending some time searching a solution I have found two updated workarounds for Angular 13.1.1:

  1. First option:
  constructor(private router: Router) {
    router.events.forEach((event) => {
      if (event instanceof NavigationStart) {
        // Your code
        // Use (event.url) to get URL that is being navigated
      }
    });
  }
  1. Second option

 routerSubscription: Subscription | undefined;

 constructor(private router: Router) {}


  ngAfterViewInit(): void {
    this.routerSubscription = this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
          // Your code
          // Use (event.url) to get URL that is being navigated
      }
    });
  }

Remember to unsubscribe on the destroy cicle

 ngOnDestroy(): void {
    this.routerSubscription?.unsubscribe();
  }

Also pay attention depending on your case if is better to use

event instanceof NavigationStart

or

event instanceof NavigationEnd

Isidoro answered 5/8, 2022 at 14:19 Comment(0)
C
12

In the component, you might want to try this:

import {NavigationEnd, NavigationStart, Router} from '@angular/router';

constructor(private router: Router) {
router.events.subscribe(
        (event) => {
            if (event instanceof NavigationStart)
                // start loading pages
            if (event instanceof NavigationEnd) {
                // end of loading paegs
            }
        });
}
Churl answered 19/4, 2019 at 5:37 Comment(0)
H
11

Location works...

import {Component, OnInit} from '@angular/core';
import {Location} from '@angular/common';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent implements OnInit {

    constructor(private location: Location) {
        this.location.onUrlChange(x => this.urlChange(x));
    }

    ngOnInit(): void {}

    urlChange(x) {
        console.log(x);
    }
}
Hydracid answered 30/12, 2019 at 23:54 Comment(0)
G
10

Capture route change events in the following manner...

import { Component, OnInit, Output, ViewChild } from "@angular/core";
import { Router, NavigationStart, NavigationEnd, Event as NavigationEvent } from '@angular/router';

@Component({
    selector: "my-app",
    templateUrl: "app/app.component.html",
    styleUrls: ["app/app.component.css"]
})
export class AppComponent {

    constructor(private cacheComponentObj: CacheComponent,
        private router: Router) {

        /*  Route event types
            NavigationEnd
            NavigationCancel
            NavigationError
            RoutesRecognized
        */
        router.events.forEach((event: NavigationEvent) => {

            //Before Navigation
            if (event instanceof NavigationStart) {
                switch (event.url) {
                case "/app/home":
                {
                    //Do Work
                    break;
                }
                case "/app/About":
                {
                    //Do Work
                    break;
                }
                }
            }

            //After Navigation
            if (event instanceof NavigationEnd) {
                switch (event.url) {
                case "/app/home":
                {
                    //Do Work
                    break;
                }
                case "/app/About":
                {
                    //Do Work
                    break;
                }
                }
            }
        });
    }
}
Goodhen answered 20/8, 2017 at 9:36 Comment(1)
Perfect, How can I get exact param.id of url ?Calcine
S
10

If you're trying to access the current route while listening to route change:

router.events.pipe(filter(r=>r instanceof NavigationEnd)).subscribe(r=>{
      console.log((r as NavigationEnd).url);
    });
Skirr answered 19/8, 2021 at 17:40 Comment(0)
I
5

above most of solutions correct , but i am facing issue this emit multiple times 'Navigation emit' event.when i was change any route this event is triggered. So hear is the complete solution for Angular 6.

import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/filter';    

export class FooComponent implements OnInit, OnDestroy {
   private _routerSub = Subscription.EMPTY;
   constructor(private router: Router){}

   ngOnInit(){
     this._routerSub = this.router.events
      .filter(event => event instanceof NavigationEnd)
      .subscribe((value) => {
         //do something with the value
     });
  }

  ngOnDestroy(){
   this._routerSub.unsubscribe();
  }
} 
Irrelevancy answered 31/10, 2018 at 7:22 Comment(0)
B
4

Updated answer for those who are using Angular9+, By using Router API provided by @angular/router and listening for route changes

import { Component } from '@angular/core';
import { Router,NavigationEnd  } from '@angular/router';

    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      
      name = 'Get Current Url Route Demo';
      currentRoute: string;
     routeSubscription: subscription;
    
      constructor(private router: Router){
        console.log(router.url);
        
        this.routeSubscription = router.events.filter(event => event instanceof NavigationEnd)
              .subscribe(event => 
               {
                  this.currentRoute = event.url;          
                  console.log(event);
               });
        }
    }
Broadside answered 13/7, 2021 at 22:57 Comment(0)
D
3

I would write something like this:

ngOnInit() {
this.routed = this.router.events.map( event => event instanceof NavigationStart )
  .subscribe(() => {
  } );
}

ngOnDestroy() {
this.routed.unsubscribe();
}
Devilfish answered 19/5, 2020 at 14:42 Comment(0)
N
2

In Angular 7, I have solved using the below function for enabling and disabling the navbar on specific pages.

First you should import NavigationEnd

import { NavigationEnd, Router } from '@angular/router';

navbar.component.ts

public isNavbar=false;
ngAfterViewInit() {

    // nabar enable / disable function
    this.router.events.subscribe((event) => {
        if (event instanceof NavigationEnd) {   
            if(event.url.includes('dashboard')){
                this.isNavbar=true;
              }else{
                this.isNavbar=false;
              }
        }
    });
}

navbar.component.html

<mat-toolbar *ngIf="isNavbar" class="mat-elevation-z1 nav-tool-bar">
<button mat-button routerLink="/dashboard" routerLinkActive="active-list-item"><svg aria-hidden="true" focusable="false" data-prefix="fal" data-icon="paper-plane" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="nav-bar-icon svg-inline--fa fa-paper-plane fa-w-16"><path fill="currentColor" d="M464 4.3L16 262.7C-7 276-4.7 309.9 19.8 320L160 378v102c0 30.2 37.8 43.3 56.7 20.3l60.7-73.8 126.4 52.2c19.1 7.9 40.7-4.2 43.8-24.7l64-417.1C515.7 10.2 487-9 464 4.3zM192 480v-88.8l54.5 22.5L192 480zm224-30.9l-206.2-85.2 199.5-235.8c4.8-5.6-2.9-13.2-8.5-8.4L145.5 337.3 32 290.5 480 32l-64 417.1z" class=""></path></svg>
    Campagnes</button>
<button mat-button routerLink="fake" routerLinkActive="active-list-item"><svg aria-hidden="true" focusable="false" data-prefix="fal" data-icon="box-open" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 608 512" class="nav-bar-icon svg-inline--fa fa-box-open fa-w-19"><path fill="currentColor" d="M606.4 143.8L557.5 41c-2.7-5.6-8.1-9-13.9-9C543 32 304 64 304 64S65 32 64.4 32c-5.8 0-11.2 3.5-13.9 9L1.6 143.8c-4.4 9.2.3 20.2 9.6 23l49.5 14.9V393c0 14.7 9.5 27.5 23 31l205.4 54.1c13 3.4 23.7 1.5 29.5 0L524.2 424c13.5-3.6 23-16.4 23-31V181.7l49.5-14.9c9.4-2.8 14-13.8 9.7-23zM73 65.3l180.9 24.3-57.1 99.8-159.9-48.1 36.1-76zm18.2 125.6C208.3 226.1 200.5 224 203.6 224c5.4 0 10.5-2.9 13.3-7.9l71.9-125.5V445L91.2 393V190.9zM516.8 393l-197.6 52V90.5L391.1 216c2.9 5 8 7.9 13.3 7.9 3.1 0-5 2.1 112.4-33.1V393zM411.3 189.3l-57.1-99.8L535 65.3l36.1 76-159.8 48z" class=""></path></svg>
    Ressources</button>
<button mat-button routerLink="fake" routerLinkActive="active-list-item"><svg aria-hidden="true" focusable="false" data-prefix="fal" data-icon="life-ring" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="nav-bar-icon svg-inline--fa fa-life-ring fa-w-16"><path fill="currentColor" d="M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm168.766 113.176l-62.885 62.885a128.711 128.711 0 0 0-33.941-33.941l62.885-62.885a217.323 217.323 0 0 1 33.941 33.941zM256 352c-52.935 0-96-43.065-96-96s43.065-96 96-96 96 43.065 96 96-43.065 96-96 96zM363.952 68.853l-66.14 66.14c-26.99-9.325-56.618-9.33-83.624 0l-66.139-66.14c66.716-38.524 149.23-38.499 215.903 0zM121.176 87.234l62.885 62.885a128.711 128.711 0 0 0-33.941 33.941l-62.885-62.885a217.323 217.323 0 0 1 33.941-33.941zm-52.323 60.814l66.139 66.14c-9.325 26.99-9.33 56.618 0 83.624l-66.139 66.14c-38.523-66.715-38.5-149.229 0-215.904zm18.381 242.776l62.885-62.885a128.711 128.711 0 0 0 33.941 33.941l-62.885 62.885a217.366 217.366 0 0 1-33.941-33.941zm60.814 52.323l66.139-66.14c26.99 9.325 56.618 9.33 83.624 0l66.14 66.14c-66.716 38.524-149.23 38.499-215.903 0zm242.776-18.381l-62.885-62.885a128.711 128.711 0 0 0 33.941-33.941l62.885 62.885a217.323 217.323 0 0 1-33.941 33.941zm52.323-60.814l-66.14-66.14c9.325-26.99 9.33-56.618 0-83.624l66.14-66.14c38.523 66.715 38.5 149.229 0 215.904z" class=""></path></svg>Support</button></mat-toolbar>

navbar.component.scss

.mat-toolbar {
    padding-top: 2px;
    padding-left: 30px;
    background-color: #fff;
  }
  ::ng-deep .nav-tool-bar{
    button{
     .mat-button-focus-overlay{
       opacity: 0!important;
     }
     .nav-bar-icon{
       width: 16px;
     }
     span{
      font-size: 15px;
     }
    }
    .active-list-item{
        background-color: #c79652;
        span{
          color: #fff;
          font-size: 15px;
          svg{
            path{
              color: #fff;
            }
          }
        }
    }
  }

Important to changes SCSS .active-list-item background color.

Nealy answered 4/11, 2015 at 10:57 Comment(0)
P
2
this.router.events.subscribe((event) => {
  if (event instanceof NavigationStart) {
    this.showProgressBar = true
  } else if (event instanceof NavigationEnd) {
    this.showProgressBar = false
  }
  else if (event instanceof NavigationCancel) {
    this.showProgressBar = false
  }
})

You can subscribe in any event route state

Paramo answered 22/11, 2022 at 16:57 Comment(0)
A
1

@Ludohen answer is great, but in case you don't want to use instanceof use the following

this.router.events.subscribe(event => {
  if(event.constructor.name === "NavigationStart") {
    // do something...
  }
});

with this way you can check the current event name as a string and if the event occurred you can do what you planned your function to do.

Antichlor answered 5/1, 2017 at 10:25 Comment(6)
why not use typescript safety?Kelso
@Kelso why the hate? and the Event type is causing an error in Atom that's why I didn't used itAntichlor
there is no hate just vote down! thats an atom problem.Kelso
@Kelso no it's an Angular problem since the router event is not the same as the browser event and that's why the Event type won't work! they need to create a new interface for this event, I should've said that from the beginning but the unreasonable down vote didn't help :)Antichlor
since minification is performed in production code you should rather use instanceOf so your example will work in production code too. if(event instanceOf NavigationStart) {Pupiparous
Should be if(event instanceof NavigationStart)Belize
O
1

I am working with angular5 application and i'm facing the same issue . when i go through Angular Documentation they provide best solution for handling router events.check following documentation.

Represents an event triggered when a navigation ends successfully

How to use this ?

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRouteSnapshot, NavigationEnd } from '@angular/router';
@Component({
    selector: 'app-navbar',
    templateUrl: './navbar.component.html',
    styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
    constructor(private router: Router) { }
    ngOnInit(): void {
        //calls this method when navigation ends
        this.router.events.subscribe(event => {
            if (event instanceof NavigationEnd) {
                //calls this stuff when navigation ends
                console.log("Event generated");
            }
        });
    }
}

When to use this ?

In my case my application share common dashboard for all users such as users , Admins , but i need to show and hides some navbar options as per user types.

That's why whenever url changes i need to call service method which returns logged in user information as per response i will go for further operations.

Outmost answered 6/10, 2018 at 10:41 Comment(0)
C
1

You can use the following to detect the route change:

import { Router, ActivatedRoute} from '@angular/router';

constructor(private route: ActivatedRoute) {}        

this.router.events.subscribe((event) => {
        if(event) {
            //do something
        }
    });
Chicago answered 22/6, 2022 at 9:16 Comment(1)
This is unnecessarily confusing. You are importing ActivatedRoute and using it in the constructor, but then the route isn't used. And property 'events' does not exist on type 'ActivatedRoute'. So basicaly you suggest using router.events just like older answers…Lightness
O
0

The following KIND of works and may do the tricky for you.

// in constructor of your app.ts with router and auth services injected
router.subscribe(path => {
    if (!authService.isAuthorised(path)) //whatever your auth service needs
        router.navigate(['/Login']);
    });

Unfortunately this redirects later in the routing process than I'd like. The onActivate() of the original target component is called before the redirect.

There is a @CanActivate decorator you can use on the target component but this is a) not centralised and b) does not benefit from injected services.

It would be great if anyone can suggest a better way of centrally authorising a route before it is committed. I'm sure there must be a better way.

This is my current code (How would I change it to listen to the route change?):

import {Component, View, bootstrap, bind, provide} from 'angular2/angular2';
import {ROUTER_BINDINGS, RouterOutlet, RouteConfig, RouterLink, ROUTER_PROVIDERS, APP_BASE_HREF} from 'angular2/router';    
import {Location, LocationStrategy, HashLocationStrategy} from 'angular2/router';

import { Todo } from './components/todo/todo';
import { About } from './components/about/about';

@Component({
    selector: 'app'
})

@View({
    template: `
        <div class="container">
            <nav>
                <ul>
                    <li><a [router-link]="['/Home']">Todo</a></li>
                    <li><a [router-link]="['/About']">About</a></li>
                </ul>
            </nav>
            <router-outlet></router-outlet>
        </div>
    `,
    directives: [RouterOutlet, RouterLink]
})

@RouteConfig([
    { path: '/', redirectTo: '/home' },
    { path: '/home', component: Todo, as: 'Home' },
    { path: '/about', component: About, as: 'About' }
])

class AppComponent {    
    constructor(location: Location){
        location.go('/');
    }    
}    
bootstrap(AppComponent, [ROUTER_PROVIDERS, provide(APP_BASE_HREF, {useValue: '/'})]);
Overton answered 4/11, 2015 at 17:25 Comment(2)
I've seen folks extend the routerOutlet to add their auth code which is one way. There's talk on gitHub about it but no conclusion yet.. Here's Auth0's way: auth0.com/blog/2015/05/14/…Tessellation
Thank you for your response. Do you know any good videos for learning the authService for angular 2?Operand
Z
0

I do it like this since RC 5

this.router.events
  .map( event => event instanceof NavigationStart )
  .subscribe( () => {
    // TODO
  } );
Zolly answered 25/8, 2016 at 13:14 Comment(0)
F
0

The cleaner way to do this would be to inherit RouteAware and implement the onNavigationEnd() method.

It's part of a library called @bespunky/angular-zen.

  1. npm install @bespunky/angular-zen

  2. Make your AppComponent extend RouteAware and add an onNavigationEnd() method.

import { Component     } from '@angular/core';
import { NavigationEnd } from '@angular/router';
import { RouteAware    } from '@bespunky/angular-zen/router-x';

@Component({
    selector   : 'app-root',
    templateUrl: './app.component.html',
    styleUrls  : ['./app.component.css']
})
export class AppComponent extends RouteAware
{    
    protected onNavigationEnd(event: NavigationEnd): void
    {
        // Handle authentication...
    }
}

RouteAware has other benefits such as:
✨ Any router event can have a handler method (Angular's supported router events).
✨ Use this.router to access the router
✨ Use this.route to access the activated route
✨ Use this.componentBus to access the RouterOutletComponentBus service

Father answered 25/2, 2021 at 17:18 Comment(0)
M
0

im using this way:

class ClassName {
  constructor(private router: Router) {
    router.events.subscribe((value) => {
        // see this 
        console.log(value instanceof NavigationEnd) 
    });
  }
}
Mallarme answered 23/3, 2021 at 19:18 Comment(0)
D
0

if you just want to check route/query paramater changes like localhost:4200/users/1?edit=1 to localhost:4200/users/2?edit=0 you can use params observable like below.

import { ActivatedRoute, Params } from '@angular/router';
export class SomeClass implements OnInit {

paramFromRoute;

constructor(private route: ActivatedRoute) { }

ngOnInit() {
  this.paramFromRoute = this.route.snapshot.params['paramName']; // this one is required for getting it first time

  this.route.params.subscribe((params:Params)=>{
    this.paramFromRoute =  params['paramName'] // whenever route is changed, this function will triggered.
  });
  // for queryParams you can subscribe to this.route.queryParams
 }   
}
Depressive answered 27/10, 2021 at 19:20 Comment(0)
B
0

You do no need to know when route changes in order to protect a route(which is the final goal ).

Angular gives you the CanActivate interface you need to create an auhtguard and asign it to the needed routes that have to be protected

https://angular.io/api/router/CanActivate

Bryson answered 13/6, 2023 at 8:29 Comment(0)
R
-1

Just make changes on AppRoutingModule like

@NgModule({
imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' })],
  exports: [RouterModule]
})
Rev answered 30/11, 2018 at 4:33 Comment(0)
L
-1

Angular 8. Check whether the current route is the base route.

  baseroute: boolean;
  constructor(
    private router: Router,
  ) {
    router.events.subscribe((val: any) => {
      if (val.url == "/") {
        this.baseroute = true;
      } else {
        this.baseroute = false;
      }
    });
  }
Lading answered 8/11, 2019 at 8:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.