Я ищу, чтобы обнаружить изменение маршрута в моем AppComponent
.
После этого я проведу глобальный токен пользователя, чтобы узнать, вошел ли он в систему. Затем я могу перенаправить пользователя, если он не вошел в систему.
Я ищу, чтобы обнаружить изменение маршрута в моем AppComponent
.
После этого я проведу глобальный токен пользователя, чтобы узнать, вошел ли он в систему. Затем я могу перенаправить пользователя, если он не вошел в систему.
В Angular 2 вы можете subscribe
(событие Rx) на экземпляр Router. Поэтому вы можете делать такие вещи, как
class MyClass {
constructor(private router: Router) {
router.subscribe((val) => /*whatever*/)
}
}
Изменить (поскольку rc.1)
class MyClass {
constructor(private router: Router) {
router.changes.subscribe((val) => /*whatever*/)
}
}
Изменить 2 (начиная с 2.0.0)
см. также: Router.events doc
class MyClass {
constructor(private router: Router) {
router.events.subscribe((val) => {
// see also
console.log(val instanceof NavigationEnd)
});
}
}
RxJS 6
router.events.pipe(filter(event => event instanceof NavigationStart))
Благодаря Peilonrayz (см. Комментарии ниже)
новый роутер> = 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
});
}
Вы также можете фильтровать по данному событию:
import 'rxjs/add/operator/filter';
constructor(router:Router) {
router.events
.filter(event => event instanceof NavigationStart)
.subscribe((event:NavigationStart) => {
// You only receive NavigationStart events
});
}
Использование pairwise
оператора для получения предыдущего и текущего события также является хорошей идеей. 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); }); }; }
Угловой 4.x и выше:
Это может быть достигнуто с использованием свойства url класса ActivatedRoute, как показано ниже,
this.activatedRoute.url.subscribe(url =>{
console.log(url);
});
Примечание. Чтобы импортировать и вводить провайдера из пакета angular/router
import { ActivatedRoute } from '@angular/router'
а также
constructor(private activatedRoute : ActivatedRoute){ }
Для Angular 7 кто-то должен написать так:
this.router.events.subscribe((event: Event) => {})
Подробный пример может быть следующим:
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 должен быть
this.router.events.subscribe(path => {
console.log('path = ', path);
});
В угловом 6 и 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*/
}
)
Angular 7, если вы хотите subscribe
на 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);
});
}
Ответы здесь верны для router-deprecated
. Для последней версии router
:
this.router.changes.forEach(() => {
// Do whatever in here
});
или
this.router.changes.subscribe(() => {
// Do whatever in here
});
Чтобы увидеть разницу между двумя, пожалуйста, ознакомьтесь с этим вопросом SO.
Edit
За последнее время вы должны:
this.router.events.subscribe(event: Event => {
// Handle route change
});
Захват событий изменения маршрута следующим образом...
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;
}
}
}
});
}
}
@Ludohen ответ велик, но если вы не хотите использовать instanceof
, используйте следующие
this.router.events.subscribe(event => {
if(event.constructor.name === "NavigationStart") {
// do something...
}
});
таким образом вы можете проверить текущее имя события как строку, и если произошло событие, вы можете делать то, что планировали выполнять свою функцию.
Я работаю с угловым приложением, и я столкнулся с той же проблемой. когда я перехожу через "Угловую документацию", они предоставляют лучшее решение для обработки событий маршрутизатора. Посмотрите следующую документацию.
События маршрутизатора в событиях углового маршрута в угловом5
Но специально для рассматриваемого случая нам нужно NavigationEnd Event
Представляет событие, инициированное при успешном завершении навигации
Как это использовать?
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");
}
});
}
}
Когда использовать это?
В моем случае мое приложение использует общую панель мониторинга для всех пользователей, таких как пользователи, администраторы, но мне нужно показать и скрывать некоторые параметры навигации в соответствии с типами пользователей.
Поэтому, когда изменяется URL-адрес, мне нужно вызвать метод службы, который возвращает данные пользователя в соответствии с ответом, и я буду продолжать дальнейшие операции.
Выше большинство решений верны, но я сталкиваюсь с проблемой, когда это событие генерировалось несколько раз. Событие Navigation emit. Когда я менял любой маршрут, это событие вызывалось. Так что слушайте это полное решение для 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();
}
}
Следующий KIND работ и может сделать сложный для вас.
// 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']);
});
К сожалению, это перенаправляется позже в процессе маршрутизации, чем хотелось бы. onActivate()
исходного целевого компонента вызывается перед перенаправлением.
Существует декодер @CanActivate
, который вы можете использовать на целевом компоненте, но это: a) не централизовано, и b) не использует внедренные службы.
Было бы здорово, если бы кто-нибудь мог предложить лучший способ централизованного разрешения маршрута до его совершения. Я уверен, что должен быть лучший способ.
Это мой текущий код (как бы изменить его, чтобы прослушать изменение маршрута?):
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: '/'})]);
Я делаю это так, так как RC 5
this.router.events
.map( event => event instanceof NavigationStart )
.subscribe( () => {
// TODO
} );
Просто внесите изменения в AppRoutingModule, как
@NgModule({
imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' })],
exports: [RouterModule]
})
В компоненте вы можете попробовать это:
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
}
});
}