web-dev-qa-db-ger.com

Wie erkennt man eine Routenänderung in Angular?

Ich freue mich auf eine Routenänderung in meiner AppComponent.

Danach werde ich das globale Benutzertoken überprüfen, um zu sehen, ob er angemeldet ist. Dann kann ich den Benutzer umleiten, falls er nicht angemeldet ist.

265
AngularM

In Angular 2 können Sie subscribe (Rx-Ereignis) zu einer Router-Instanz . So können Sie beispielsweise Folgendes tun

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

Edit (seit rc.1)

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

Edit 2 (seit 2.0.0)

siehe auch: Router.events doc

class MyClass {
  constructor(private router: Router) {
    router.events.subscribe((val) => {
        // see also 
        console.log(val instanceof NavigationEnd) 
    });
  }
}
344
Ludohen

RxJS 6

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

Danke an Peilonrayz (siehe Kommentare unten)

neuer 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
  });
}

Sie können auch nach dem angegebenen Ereignis filtern: 

import 'rxjs/add/operator/filter';

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

Die Verwendung des Operators pairwise zum Abrufen des vorherigen und aktuellen Ereignisses ist ebenfalls eine schöne Idee. 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);
        });
    };
}
252

Für Angular 7 sollte jemand schreiben wie:

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


Ein detailliertes Beispiel kann wie folgt aussehen:

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);
            }
        });

   }
}

Winkel 4.x und höher: 

Dies kann mit der URL-Eigenschaft der ActivatedRoute class wie folgt erreicht werden:

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

Hinweis: Sie müssen den Anbieter aus dem angular/router-Paket importieren und einfügen

import { ActivatedRoute } from '@angular/router`

und 

constructor(private activatedRoute : ActivatedRoute){  }
35
Aravind

Router 3.0.0-beta.2 sollte sein

this.router.events.subscribe(path => {
  console.log('path = ', path);
});
16
Mike Lallemont

In Winkel 6 und 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*/
}
)
15
JBRandri

Die Antworten hier sind für router-deprecated korrekt. Für die neueste Version von router :

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

oder

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

Um den Unterschied zwischen den beiden zu sehen, überprüfen Sie bitte diese SO - Frage .

Bearbeiten

Für das späteste müssen Sie tun: 

this.router.events.subscribe(event: Event => {
    // Handle route change
});
13
Dehli

Winkel 6, wenn Sie subscribe zu router wollen

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);
  });
}
10
Druta Ruslan

Erfassen Sie Routenänderungsereignisse auf folgende Weise ... 

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;
                }
                }
            }
        });
    }
}
5
Narottam Goyal

@Ludohen Die Antwort ist großartig. Falls Sie jedoch instanceof nicht verwenden möchten, verwenden Sie Folgendes

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

auf diese Weise können Sie den Namen des aktuellen Ereignisses als Zeichenfolge überprüfen und wenn das Ereignis aufgetreten ist, können Sie tun, was Sie für Ihre Funktion geplant haben. 

2

In der Komponente möchten Sie möglicherweise Folgendes versuchen:

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
            }
        });
}
1

Ich arbeite mit der Anwendung angle5 und ich stehe vor demselben Problem. Wenn ich die Angular-Dokumentation durchsehe, bieten sie die beste Lösung für den Umgang mit Router-Ereignissen. Überprüfen Sie die folgende Dokumentation.

Stellt ein Ereignis dar, das ausgelöst wird, wenn eine Navigation erfolgreich beendet wird

Wie benutzt man das?

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");
            }
        });
    }
}

Wann benutzt man das?

In meinem Fall gibt es für meine Anwendung ein gemeinsames Dashboard für alle Benutzer, z. B. Benutzer, Administratoren. Ich muss jedoch einige Navbar-Optionen je nach Benutzertyp anzeigen und ausblenden.

Aus diesem Grund muss bei jeder Änderung der URL die Servicemethode aufgerufen werden, die als Antwort angemeldete Benutzerinformationen zurückgibt. Ich werde weitere Operationen ausführen.

1
Bhagvat Lande

über den meisten Lösungen korrekt, aber ich stehe vor dem Problem, dass dieses Ereignis mehrmals ausgegeben wird. Das Ereignis "Navigation emit" wird ausgelöst. Also hören Sie die komplette Lösung für 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();
  }
} 
1
yala ramesh

Ich mache das seit RC 5 so

this.router.events
  .map( event => event instanceof NavigationStart )
  .subscribe( () => {
    // TODO
  } );
0
jirigracik

Die folgende Art von Arbeiten und kann das schwierigste für Sie tun.

// 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']);
    });

Leider leitet dies später im Routing-Prozess um, als ich möchte. Die onActivate() der ursprünglichen Zielkomponente wird vor der Weiterleitung aufgerufen.

Es gibt einen @CanActivate-Dekorator, den Sie für die Zielkomponente verwenden können. Dies ist jedoch a) nicht zentralisiert und b) profitiert nicht von injizierten Services.

Es wäre großartig, wenn jemand eine bessere Möglichkeit vorschlagen könnte, eine Route zentral zu autorisieren, bevor sie festgelegt wird. Ich bin sicher, dass es einen besseren Weg geben muss.

Dies ist mein aktueller Code (Wie würde ich ihn ändern, um die Routenänderung zu hören?):

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: '/'})]);
0
Richard Evans

Nehmen Sie einfach Änderungen an AppRoutingModule vor

@NgModule({
imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' })],
  exports: [RouterModule]
})
0
Pullat Junaid