Odpowiedzi:
W Angular 2 możesz subscribe
(zdarzenie Rx) do instancji routera. Możesz więc robić takie rzeczy jak
class MyClass {
constructor(private router: Router) {
router.subscribe((val) => /*whatever*/)
}
}
Edytuj (od rc.1)
class MyClass {
constructor(private router: Router) {
router.changes.subscribe((val) => /*whatever*/)
}
}
Edycja 2 (od 2.0.0)
patrz także: Router.events doc
class MyClass {
constructor(private router: Router) {
router.events.subscribe((val) => {
// see also
console.log(val instanceof NavigationEnd)
});
}
}
filter
operatora RxJS . router.events.pipe(filter(e => e instanceof NavigationEnd).subscribe((e) => { ... }
RxJS 6
router.events.pipe(filter(event => event instanceof NavigationStart))
Dzięki Peilonrayz (patrz komentarze poniżej)
nowy 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
});
}
Możesz również filtrować według danego zdarzenia:
import 'rxjs/add/operator/filter';
constructor(router:Router) {
router.events
.filter(event => event instanceof NavigationStart)
.subscribe((event:NavigationStart) => {
// You only receive NavigationStart events
});
}
Dobrym pomysłem jest także skorzystanie z pairwise
operatora w celu uzyskania poprzedniego i bieżącego wydarzenia. 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); }); }; }
Argument of type '(event: Event) => void' is not assignable to parameter of type
Argument of type '(event: Event) => void' is not assignable to parameter of type
błąd polega na tym, że we fragmencie filtra subskrybujesz obiekt typu Event zamiast NavigationEvent.
W Angular 7 ktoś powinien napisać:
this.router.events.subscribe((event: Event) => {})
Szczegółowy przykład może wyglądać następująco:
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);
}
});
}
}
Kątowe 7 , jeśli chcesz subscribe
, abyrouter
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);
});
}
Kątowy 4.xi wyższy:
Można to osiągnąć za pomocą właściwości url klasy ActivatedRoute, jak poniżej,
this.activatedRoute.url.subscribe(url =>{
console.log(url);
});
Uwaga:
Musisz zaimportować i wstrzyknąć dostawcę z angular/router
paczki
import { ActivatedRoute } from '@angular/router`
i
constructor(private activatedRoute : ActivatedRoute){ }
Router 3.0.0-beta.2 powinien być
this.router.events.subscribe(path => {
console.log('path = ', path);
});
W kątach 6 i 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*/
}
)
import {Router, NavigationEnd} from "@angular/router"
Odpowiedzi tutaj są poprawne dla router-deprecated
. Najnowsza wersja router
:
this.router.changes.forEach(() => {
// Do whatever in here
});
lub
this.router.changes.subscribe(() => {
// Do whatever in here
});
Aby zobaczyć różnicę między nimi, sprawdź to SO pytanie .
Edytować
Najpóźniej musisz zrobić:
this.router.events.subscribe(event: Event => {
// Handle route change
});
router
Został ponownie zaktualizowany (I nie zostały zaktualizowane jeszcze moją odpowiedź), więc nie jestem pewien, jak to jest ostatni. W przypadku router
, o którym pisałem, nie można. @akn
W Angular 8 powinieneś to lubić this.router.events.subscribe((event: Event) => {})
Przykład:
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
}
});
}
}
W komponencie możesz spróbować tego:
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
}
});
}
Rejestruj zdarzenia zmiany trasy w następujący sposób ...
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;
}
}
}
});
}
}
Lokalizacja działa ...
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);
}
}
powyżej większość rozwiązań jest poprawnych, ale mam do czynienia z problemem, który emituje wiele razy zdarzenie „Emituj nawigację”. kiedy zmieniłem dowolną trasę, to zdarzenie jest wyzwalane. Więc usłysz to kompletne rozwiązanie dla Angulara 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();
}
}
Odpowiedź @Ludohen jest świetna, ale jeśli nie chcesz używać, instanceof
skorzystaj z poniższych
this.router.events.subscribe(event => {
if(event.constructor.name === "NavigationStart") {
// do something...
}
});
w ten sposób możesz sprawdzić nazwę bieżącego zdarzenia jako ciąg znaków, a jeśli zdarzenie wystąpiło, możesz zrobić to, co zaplanowałeś.
Event
typ powoduje błąd w Atomie, dlatego go nie użyłem
instanceOf
aby twój przykład działał również w kodzie produkcyjnym. if(event instanceOf NavigationStart) {
if(event instanceof NavigationStart)
Pracuję z aplikacją angular5 i mam ten sam problem. kiedy przeglądam Dokumentację kątową, zapewniają najlepsze rozwiązanie do obsługi zdarzeń routera. sprawdź następującą dokumentację.
Zdarzenia routera w Angular Zdarzenia trasy w angular5
Ale specjalnie dla przypadku, o którym mowa, potrzebujemy zdarzenia NavigationEnd
Reprezentuje zdarzenie wyzwalane, gdy nawigacja zakończy się pomyślnie
Jak tego użyć?
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");
}
});
}
}
Kiedy tego użyć?
W moim przypadku moja aplikacja ma wspólny pulpit nawigacyjny dla wszystkich użytkowników, takich jak użytkownicy, administratorzy, ale muszę pokazać i ukryć niektóre opcje paska nawigacyjnego zgodnie z typami użytkowników.
Dlatego za każdym razem, gdy zmienia się adres URL, muszę wywołać metodę usługi, która zwraca zalogowane informacje o użytkowniku zgodnie z odpowiedzią, idę do dalszych operacji.
Poniższy RODZAJ prac i może zrobić dla ciebie podstęp.
// 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']);
});
Niestety przekierowuje to później w procesie routingu, niż chciałbym. TheonActivate()
Oryginalnego komponentu docelowego nazywa się przed przekierowaniem.
Tam jest @CanActivate
dekorator, którego można użyć na komponencie docelowym, ale jest to a) nie scentralizowane i b) nie korzysta z wstrzykiwanych usług.
Byłoby wspaniale, gdyby ktokolwiek mógł zasugerować lepszy sposób centralnego autoryzowania trasy przed jej zatwierdzeniem. Jestem pewien, że musi być lepszy sposób.
To jest mój bieżący kod (Jak mógłbym go zmienić, aby słuchać zmiany trasy?):
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: '/'})]);
Tak robię od RC 5
this.router.events
.map( event => event instanceof NavigationStart )
.subscribe( () => {
// TODO
} );
Po prostu wprowadź zmiany w AppRoutingModule, takie jak
@NgModule({
imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' })],
exports: [RouterModule]
})
Napisałbym coś takiego:
ngOnInit() {
this.routed = this.router.events.map( event => event instanceof NavigationStart )
.subscribe(() => {
} );
}
ngOnDestroy() {
this.routed.unsubscribe();
}
event._root.children[0].value._routeConfig.data
mam nadzieję, że może być lepszy sposób