Açısal'da bir rota değişikliği nasıl tespit edilir?


428

Ben bir rota değişikliği tespit etmek arıyorum AppComponent.

Daha sonra giriş yaptığını görmek için global kullanıcı belirtecini kontrol edeceğim. Daha sonra giriş yapmamışsa kullanıcıyı yeniden yönlendirebilirim.

Yanıtlar:


534

Açısal 2'de subscribebir Yönlendirici örneğine (Rx olayı) yapabilirsiniz . Yani böyle şeyler yapabilirsiniz

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

Düzenle (rc.1'den beri)

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

Düzenleme 2 (2.0.0'dan beri)

ayrıca bakınız: Router.events doc

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

2
Ben event._root.children[0].value._routeConfig.datadaha iyi bir yol olabilir umarım veri elde edebiliyoruz
Akshay

6
@Akshay, Todd Motto'nun bu makalesini gördünüz: [Angular 2'deki yönlendirici olaylarıyla dinamik sayfa başlıkları] ( toddmotto.com/dynamic-page-titles-angular-2-router-events )
Bogac

10
neden 3 kez ateş ediyor?
Araç Seti

2
@Toolkit, çünkü etkinliğin 3 durumu ve başarılı bir url değişikliği var. 3 durum: 'NavigationStart', 'NavigationEnd' ve 'RoutesRecognized'
RicardoGonzales

10
RxJS filteroperatörü ile olayları kolayca filtreleyebilirsiniz . router.events.pipe(filter(e => e instanceof NavigationEnd).subscribe((e) => { ... }
Simon_Weaver

314

RxJS 6

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

Peilonrayz sayesinde (aşağıdaki yorumlara bakınız)

yeni yönlendirici> = 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
  });
}

Ayrıca verilen etkinliğe göre de filtreleyebilirsiniz:

import 'rxjs/add/operator/filter';

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

Önceki ve güncel olayı almak için pairwiseoperatörü kullanmak da iyi bir fikirdir. 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);
        });
    };
}

1
@GunterZochbauer yerine 'is' kullanırım 'instanceof'. Ve 'event: Event' parantez içinde olmalıdır. Bunun için teşekkürler, oldukça güçlü yeni özellik! Bunun gibi
Maxim

2
Bu, mevcut sürümlerde bir derleme hatası Argument of type '(event: Event) => void' is not assignable to parameter of type
atıyor

1
@RudiStrydom & Günter Zöchbauer - Argument of type '(event: Event) => void' is not assignable to parameter of typehata, filtre snippet'inizde NavigationEvent yerine Event türündeki bir nesneye abone olmanızdır.
Bonnici

1
İkinci örnek Olay yerine NavigationEvent olmalıdır. Ayrıca @ açısal / yönlendiriciden "EventE NavigationEvent" i almayı unutmayın
Mick

1
İçe aktarma ile ilgili ipucu bu hatayı çözmek isteyen herkes içindi :)
Mick

92

İçin açısal 7 birisi gibi yazmalıdır:

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


Ayrıntılı bir örnek aşağıdaki gibi olabilir:

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

   }
}

2
Bu harika! çok kapsamlı! Angular 7'de mükemmel çalıştı.
MaylorTaylor

1
Önceden yükleme stratejisini kullanırsanız genellikle navigasyonun kendisi çok az zaman alır. Kullanılabilirlik açısından, yükleme göstergelerini yalnızca arka uç http isteklerinde kullanırım.
Phil

5
Gelen yapıcı , sen <Bu> davanızKraliyet ngOnInit içindir kullanmamalısınız.
Sergio Reis

1
Mükemmel, URL'nin tam param.id değerini nasıl alabilirim?
ShibinRagh

2
Çözüm bileşenle sınırlı değildir, kaynak tüketerek uygulama genelinde yayılır
Md. Rafee

54

7 Eğik , eğer istersen subscribeetmekrouter

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

2
yönlendirme etkinliğini yakalamaz
Anandhu Ajayakumar

40

Açısal 4.x ve üstü:

Bu, ActivatedRoute sınıfının url özelliği kullanılarak aşağıdaki gibi elde edilebilir ,

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

Not: Sağlayıcıyı angular/routerpaketten içe aktarmanız ve enjekte etmeniz gerekir

import { ActivatedRoute } from '@angular/router`

ve

constructor(private activatedRoute : ActivatedRoute){  }

18

Yönlendirici 3.0.0-beta.2 olmalıdır

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

şu anki yol için çalışıyor ama ya önceki?
tatsu

16

Açısal 6 ve RxJS6'da:

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*/
}
)

3
Router için ithalat kaçırdınızimport {Router, NavigationEnd} from "@angular/router"
Damir Beylkhanov

15

Buradaki cevaplar doğru router-deprecated. Şunun en son sürümü için router:

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

veya

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

İkisi arasındaki farkı görmek için lütfen bu SO sorusuna göz atın .

Düzenle

En son için yapmanız gerekenler:

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

Önceki ve geçerli rotadan herhangi bir veri sağlıyor mu?
16'da akn

Yine routergüncellendi (Cevabımı henüz güncellemedim), bu yüzden en son nasıl olduğundan emin değilim. Çünkü routeryazdım, yapamazsın. @akn
Dehli

Lütfen bu cevap için bir bağlam sağlayabilir misiniz? diğer çözümlerde hangi satırları sizinkilerle değiştiriyorsunuz?
Gerard Simpson

12

Açısal 8'de şunları yapmalısınız: this.router.events.subscribe((event: Event) => {})

Misal:

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

10

Bileşende, şunu denemek isteyebilirsiniz:

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

8

Güzergah değişikliği olaylarını aşağıdaki şekilde yakalayın ...

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

Mükemmel, URL'nin tam param.id değerini nasıl alabilirim?
ShibinRagh

6

Konum çalışmaları ...

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

Güzel cevap. benim durumum için çalışıyor. Teşekkürler
Umar Tariq

4

çoğu çözüm doğru yukarıda, ancak bu sorun karşılaştığım bu birden fazla kez 'Gezinme yayar' olayı. herhangi bir rota değiştirmek oldu zaman bu olay tetiklenir. Yani duymak Açısal 6 için komple bir çözümdür.

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

3

@Ludohen cevap harika, ancak kullanmak istemiyorsanız instanceofaşağıdakileri kullanın

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

bu şekilde geçerli olay adını dize olarak kontrol edebilirsiniz ve olay meydana geldiğinde işlevinizi yapmayı planladığınız şeyi yapabilirsiniz.


3
neden daktilo güvenliği kullanmıyorsunuz?
Pascal

@Pascal neden nefret? ve Eventtür Atom'da hataya neden oluyor, bu yüzden onu kullanmadım
Khaled Al-Ansari

2
@Pascal hayır Yönlendirici olayı tarayıcı olayıyla aynı olmadığından bu Açısal bir sorundur ve bu yüzden Olay türü çalışmaz! Bu etkinlik için yeni bir arayüz oluşturmaları gerekiyor, bunu en baştan söylememeliydim ama mantıksız aşağı oylama yardımcı olmadı :)
Khaled Al-Ansari

5
üretim kodunda küçültme yapıldığından instanceOf, örneğin üretim kodunda da çalışmasını tercih etmelisiniz . if(event instanceOf NavigationStart) {
Milan Jaric

1
Olmalıif(event instanceof NavigationStart)
Ketan

1

Angular5 uygulaması ile çalışıyorum ve aynı sorunla karşı karşıyayım. Açısal Belgelerden geçerken yönlendirici olaylarını işlemek için en iyi çözümü sağlarlar. aşağıdaki belgeleri kontrol edin.

Gezinme başarıyla sona erdiğinde tetiklenen bir etkinliği temsil eder

Bu nasıl kullanılır?

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

Ne zaman kullanılır?

Benim durumumda, uygulama, kullanıcılar, Yöneticiler gibi tüm kullanıcılar için ortak kontrol panelini paylaşıyorum, ancak kullanıcı türlerine göre bazı navbar seçeneklerini göstermem ve gizlemem gerekiyor.

Bu nedenle url değiştiğinde, yanıt olarak oturum açmış kullanıcı bilgilerini döndüren hizmet yöntemini çağırmam gerekiyor, çünkü daha sonraki işlemler için gideceğim.


0

Aşağıdaki KIND çalışır ve sizin için zor olabilir.

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

Ne yazık ki bu, yönlendirme sürecinde istediğimden daha sonra yönlendiriyor. onActivate()Orijinal hedef bileşeninin yönlendirme öncesinde denir.

@CanActivateHedef bileşen üzerinde kullanabileceğiniz bir dekoratör var ama bu a) merkezi değil ve b) enjekte edilen hizmetlerden faydalanmıyor.

Herhangi bir işin yapılmadan önce merkezi olarak yetkilendirmenin daha iyi bir yolunu önermek harika olurdu. Eminim daha iyi bir yol olmalı.

Bu geçerli kodum (Güzergah değişikliğini dinlemek için nasıl değiştirebilirim?):

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

Millet bir yolu olan kendi kimlik kodu eklemek için routerOutlet genişletmek gördüm. GitHub'da bu konuda bir konuşma var ama henüz bir sonuç yok .. İşte Auth0'ın yolu: auth0.com/blog/2015/05/14/…
Dennis Smolek

Cevabınız için teşekkürler. AuthService açısal 2'yi öğrenmek için iyi videolar biliyor musunuz?
AngularM

0

RC 5'ten beri böyle yapıyorum

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

0

Sadece AppRoutingModule üzerinde değişiklikler yapın

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

0

Açısal 8. Geçerli rotanın temel rota olup olmadığını kontrol edin .

  baseroute: boolean;
  constructor(
    private router: Router,
  ) {
    router.events.subscribe((val: any) => {
      if (val.url == "/") {
        this.baseroute = true;
      } else {
        this.baseroute = false;
      }
    });
  }

0

Ben böyle bir şey yazmak istiyorum:

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

ngOnDestroy() {
this.routed.unsubscribe();
}

-3

Açısal 8 için basit cevap. *

constructor(private route:ActivatedRoute) {
  console.log(route);
}

1
Bu sadece örnekleme ile ilgili değil, sadece bir kere !? Bu bir çözüm değil.
Satria
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.