page - ¿Cómo detectar un cambio de ruta en Angular?
router angular navigationend (16)
Estoy buscando detectar un cambio de ruta en mi
AppComponent
.
Posteriormente, comprobaré el token de usuario global para ver si ha iniciado sesión. Luego, puedo redirigir al usuario si no ha iniciado sesión.
Capture eventos de cambio de ruta de la siguiente manera ...
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
}
});
}
Angular 4.xy superior:
Esto se puede lograr utilizando la propiedad url de la clase ActivatedRoute como se muestra a continuación,
import { ActivatedRoute } from ''@angular/router`
Nota:
que necesita importar e inyectar el proveedor del paquete
angular/router
constructor(private activatedRoute : ActivatedRoute){ }
y
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);
});
}
El siguiente TIPO de trabajos y puede hacer el truco para usted.
// 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'']);
});
Desafortunadamente, esto redirige más tarde en el proceso de enrutamiento de lo que me gustaría.
El
onActivate()
del componente de destino original se llama antes de la redirección.
Hay un decorador
@CanActivate
que puede usar en el componente de destino, pero este es a) no centralizado yb) no se beneficia de los servicios inyectados.
Sería genial si alguien puede sugerir una mejor manera de autorizar centralmente una ruta antes de que se comprometa. Estoy seguro de que debe haber una mejor manera.
Este es mi código actual (¿Cómo lo cambiaría para escuchar el cambio de ruta?):
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: ''/''})]);
En Angular 2 puede
subscribe
(evento Rx) a una instancia de enrutador.
Entonces puedes hacer cosas como
class MyClass {
constructor(private router: Router) {
router.subscribe((val) => /*whatever*/)
}
}
Editar (desde rc.1)
class MyClass {
constructor(private router: Router) {
router.changes.subscribe((val) => /*whatever*/)
}
}
Edición 2 (desde 2.0.0)
ver también: Router.events doc
class MyClass {
constructor(private router: Router) {
router.events.subscribe((val) => {
// see also
console.log(val instanceof NavigationEnd)
});
}
}
En angular 6 y 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*/
}
)
En el componente, es posible que desee probar esto:
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;
}
}
}
});
}
}
Estoy trabajando con la aplicación angular5 y estoy enfrentando el mismo problema. Cuando reviso la documentación angular, proporcionan la mejor solución para manejar los eventos del enrutador. Verifique la siguiente documentación.
-
Eventos de enrutador en eventos de ruta angular en angular5
-
Pero específicamente para el caso en cuestión, necesitamos el evento NavigationEnd
Representa un evento desencadenado cuando una navegación finaliza correctamente
Como usar esto ?
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();
}
}
¿Cuándo usar esto?
En mi caso, mi aplicación comparte un tablero común para todos los usuarios, como usuarios, administradores, pero necesito mostrar y ocultar algunas opciones de la barra de navegación según los tipos de usuarios.
Es por eso que cada vez que cambia la URL, necesito llamar al método de servicio que devuelve la información de usuario registrada según la respuesta, iré para más operaciones.
Las respuestas aquí son correctas para
router-deprecated
.
Para la última versión del
router
:
this.router.changes.forEach(() => {
// Do whatever in here
});
o
this.router.changes.subscribe(() => {
// Do whatever in here
});
Para ver la diferencia entre los dos, consulte esta pregunta SO .
Editar
Para lo último debes hacer:
this.router.events.subscribe(event: Event => {
// Handle route change
});
Lo hago así desde RC 5
this.router.events
.map( event => event instanceof NavigationStart )
.subscribe( () => {
// TODO
} );
Para Angular 7, alguien debería escribir como:
this.router.events.subscribe((event: Event) => {})
Un ejemplo detallado puede ser el siguiente:
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);
}
});
}
}
Router 3.0.0-beta.2 debería ser
this.router.events.subscribe(path => {
console.log(''path = '', path);
});
Simplemente haga cambios en AppRoutingModule como
@NgModule({
imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: ''enabled'' })],
exports: [RouterModule]
})
arriba, la mayoría de las soluciones son correctas, pero estoy enfrentando un problema que emite varias veces el evento ''Navigation emit''. Cuando cambié alguna ruta, este evento se activa. Entonces escuchar es la solución completa para Angular 6.
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");
}
});
}
}
Angular 7
, si desea
subscribe
al
router
this.activatedRoute.url.subscribe(url =>{
console.log(url);
});
La
respuesta de
@Ludohen
es excelente, pero en caso de que no desee utilizar la
instanceof
use lo siguiente
this.router.events.subscribe(event => {
if(event.constructor.name === "NavigationStart") {
// do something...
}
});
de esta manera, puede verificar el nombre del evento actual como una cadena y, si ocurrió el evento, puede hacer lo que planeó que hiciera su función.
RxJS 6
router.events.pipe(filter(event => event instanceof NavigationStart))
Gracias a Peilonrayz (ver comentarios a continuación)
nuevo enrutador> = 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
});
}
También puede filtrar por evento dado:
import ''rxjs/add/operator/filter'';
constructor(router:Router) {
router.events
.filter(event => event instanceof NavigationStart)
.subscribe((event:NavigationStart) => {
// You only receive NavigationStart events
});
}
Usar el
operador por
pairwise
para obtener el evento anterior y actual también es una buena 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); }); }; }