Angular'da önceki sayfa URL'si nasıl belirlenir?


101

Şu anda URL'yi içeren sayfadayım varsayalım /user/:id. Şimdi bu sayfadan bir sonraki sayfaya geçiyorum :id/posts.

Şimdi bir yol var mı, böylece önceki URL'nin ne olduğunu kontrol edebilirim, yani /user/:id.

Rotalarım aşağıdadır

export const routes: Routes = [
  { 
    path: 'user/:id', component: UserProfileComponent
  },
  {  
    path: ':id/posts', component: UserPostsComponet 
  }
];

Yanıtlar:


80

Rota değişikliklerine abone olabilir ve mevcut olayı kaydedebilir, böylece bir sonraki olduğunda onu kullanabilirsiniz.

previousUrl: string;
constructor(router: Router) {
  router.events
  .pipe(filter(event => event instanceof NavigationEnd))
  .subscribe((event: NavigationEnd) => {
    console.log('prev:', event.url);
    this.previousUrl = event.url;
  });
}

Ayrıca bkz . Angular'da bir rota değişikliği nasıl tespit edilir?


12
Teşekkürler @ Günter Günümü hep kurtarıyorsun.
Chandra Shekhar

30
Bu benim için önceki rotayı değil, yalnızca mevcut rotayı listeliyor.
David Aguirre

2
Ne beklediğinize bağlı. İlk seferinde nullönceden bir rota olmadığı için. Bunu kök yönlendiricide de yapmanız gerekir, aksi takdirde yalnızca bu bileşenin alt yolları arasında gezinirken alırsınız.
Günter Zöchbauer

8
Bu, kurucu ilk kez çalıştırıldığında önceki URL'yi vermez.
Ekaitz Hernandez Troyas

9
Yapıcı ilk kez çalıştırıldığında önceki url olarak hangi değeri bekliyorsunuz?
Günter Zöchbauer

110

Belki diğer tüm cevaplar açısal 2.X içindir.

Şimdi açısal 5.X için çalışmıyor. Onunla çalışıyorum.

sadece NavigationEnd ile, önceki url'yi alamazsınız.

Çünkü Yönlendirici "Navigasyon Başlangıcı", "Rotalar Tanınan", ..., "Gezinme Sonu" arasında çalışır.

İle kontrol edebilirsiniz

    router.events.forEach((event) => {
  console.log(event);
});

Ama yine de "NavigationStart" ile bile önceki URL'yi alamazsınız.

Şimdi ikili kullanmanız gerekiyor.

import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/pairwise';

constructor(private router: Router) {
  this.router.events
    .filter(e => e instanceof RoutesRecognized)
    .pairwise()
    .subscribe((event: any[]) => {
      console.log(event[0].urlAfterRedirects);
    });
}
    

İkili ile, hangi url'nin nereden ve ne olduğunu görebilirsiniz.

"RoutesRecognized", başlangıç ​​noktasından hedef url'ye değişen adımdır.

bu yüzden filtreleyin ve ondan önceki url'yi alın.

Sonuncu ama bir o kadar önemli,

bu kodu üst bileşene veya daha üstüne (ör. app.component.ts) yerleştirin

çünkü bu kod yönlendirme bittikten sonra tetiklenir.

Angular 6+ güncelleme

events.filterFiltre olayların bir parçası değildir, bu yüzden hiç kodunu değiştirmek çünkü hata veriyor

import { filter, pairwise } from 'rxjs/operators';

this.router.events
.pipe(filter((evt: any) => evt instanceof RoutesRecognized), pairwise())
.subscribe((events: RoutesRecognized[]) => {
  console.log('previous url', events[0].urlAfterRedirects);
  console.log('current url', events[1].urlAfterRedirects);
});

2
Bir hizmet olarak uygulandı ve harika çalışıyor. Açısal 6.1.7 kullanıyorum.
A. El Idrissi

5
@ tjvg1991 Sayfanın yenilenmesi, bellek verilerini kaybettiğiniz anlamına gelir. önceki verileri saklarsanız, localStorage veya çerez kullanmanız gerekir. (save yerel değil belleğe veri)
BYUNGJU Jin

Sadece Yukarı Oy düğmesini öldürmek istiyorum Teşekkürler dostum.
Muhammed Umair

@BYUNGJUJIN Bunun için teşekkürler!
john

@ BYUNGJU JIN teşekkür ederim benim için çalışıyor. param değerini yönlendirme bağlantısından nasıl alırım örneğin olaylar [0] .urlAfterRedirects bana '/ envanterDetails; test = 0; id = 45' verir, bundan id değerini almak istiyorum. SubString kullanmadan nasıl yapabilirim.
JNPW

49

Enjekte edilebilir bir hizmet oluşturun:

import { Injectable } from '@angular/core';
import { Router, RouterEvent, NavigationEnd } from '@angular/router';

 /** A router wrapper, adding extra functions. */
@Injectable()
export class RouterExtService {

  private previousUrl: string = undefined;
  private currentUrl: string = undefined;

  constructor(private router : Router) {
    this.currentUrl = this.router.url;
    router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {        
        this.previousUrl = this.currentUrl;
        this.currentUrl = event.url;
      };
    });
  }

  public getPreviousUrl(){
    return this.previousUrl;
  }    
}

O zaman ihtiyacınız olan her yerde kullanın. Mevcut değişkeni mümkün olan en kısa sürede depolamak için, hizmeti AppModule'da kullanmak gerekir.

// AppModule
export class AppModule {
  constructor(private routerExtService: RouterExtService){}

  //...

}

// Using in SomeComponent
export class SomeComponent implements OnInit {

  constructor(private routerExtService: RouterExtService, private location: Location) { } 

  public back(): void {
    this.location.back();
  }

  //Strange name, but it makes sense. Behind the scenes, we are pushing to history the previous url
  public goToPrevious(): void {
    let previous = this.routerExtService.getPreviousUrl();

    if(previous)
      this.routerExtService.router.navigateByUrl(previous);
  }

  //...

}

2
Bunun en zarif çözüm olduğunu düşünüyorum. Bu kodu yeni filtre ve ikili çözümle birleştirmeyi deneyin: stackoverflow.com/a/35287471/518879
danger89

2
Ps. Bu RouterExtService'i apps-routing.module.ts'e (benim durumumda) eklemeyi unutmayın, şöyle:@NgModule({ ..., providers: [RouterExtService]}) export class AppRoutingModule { }
danger89

Tamam, bu servis çözümüyle ilgili büyük bir sorun var .. Benim durumumda routerExtService.getPreviousUrl(), bir bileşende kullanılan bir servisin yapıcısındaki yöntemi çağırıyorum . Bazı nedenlerden dolayı bu, gerçek güncellemeden daha önce çağrıldı. Yani bir zamanlama bağımlılığımız var! Konu kullanmanın çok daha kolay olduğunu düşünüyorum.
tehlike89

Küçük bir projede benim için iyi çalıştı. Belki ihtiyaçlarınıza uyması için biraz ince ayar gerekiyor. Sorunu çözdünüz mü?
Juliano

Durumumu URL'mde 'saklamak' için şu anda sözde URL Matrisi parametrelerini kullanıyorum, varsayılan olarak tarayıcı URL'si geri düğmesini kullanırken durumu şimdi kaydediyor. let params = new HttpParams({fromString: retrieveURL}).set('name', 'victor') const paramsObject = params.keys().reduce((obj, key) => { obj[key] = params.get(key) return obj }, {}) this.router.navigate([paramsObject], { relativeTo: this.route })
danger89

20

Önceki URL'yi dize olarak almak için açısal 6 güncellenmiş kod.

import { Router, RoutesRecognized } from '@angular/router';
import { filter, pairwise } from 'rxjs/operators';


export class AppComponent implements OnInit {

    constructor (
        public router: Router
    ) {
    }

    ngOnInit() {
        this.router.events
            .pipe(filter((e: any) => e instanceof RoutesRecognized),
                pairwise()
            ).subscribe((e: any) => {
                console.log(e[0].urlAfterRedirects); // previous url
            });
    }

Bu, bir koruma tarafından engellenen url'yi döndürür, yalnızca etkinleştirilen önceki URL'yi almanın bir yolu var mı (koruma tarafından engellenmemiş)?
Exocomp

1
Gözlemlenebilir yönlendiriciden abonelikten çıkmanın en iyi yolu hakkında herhangi bir ipucu var mı?
j4v1

İşler! "NavigationEnd" in neden çalışmadığını gerçekten bilmiyorum
davidwillianx

13

Bu, açısal> = 6.x sürümlerinde benim için çalıştı:

this.router.events
            .subscribe((event) => {
              if (event instanceof NavigationStart) {
                window.localStorage.setItem('previousUrl', this.router.url);
              }
            });

10

Angular 8 kullanıyorum ve @ franklin-pious cevabı sorunu çözüyor. Benim durumumda, bir abonelik içindeki önceki url'yi almak, görünümdeki bazı verilerle eklenmişse bazı yan etkilere neden olur.

Kullandığım geçici çözüm, önceki url'yi rota navigasyonunda isteğe bağlı bir parametre olarak göndermekti.

this.router.navigate(['/my-previous-route', {previousUrl: 'my-current-route'}])

Ve bu değeri bileşende elde etmek için:

this.route.snapshot.paramMap.get('previousUrl')

this.router ve this.route, her bileşenin yapıcısının içine enjekte edilir ve @ angular / router üyeleri olarak içe aktarılır.

import { Router, ActivatedRoute }   from '@angular/router';

10

2019 sürümünde Angular 8 ve rxjs 6

Diğer harika çözümlere dayalı çözümü paylaşmak istiyorum.

Önce rota değişikliklerini dinlemek için bir hizmet oluşturun ve bir Davranış Konusunda önceki son rotayı kaydedin, ardından bu hizmeti ana uygulamada sağlayın. Bileşen kurucuda, ardından istediğiniz zaman istediğiniz önceki rotayı almak için bu hizmeti kullanın.

kullanım örneği: kullanıcıyı bir reklam sayfasına yeniden yönlendirmek ve ardından geldiği yere otomatik olarak yeniden yönlendirmek istiyorsanız, bunu yapmak için önceki son rotaya ihtiyacınız var.

// service : route-events.service.ts

import { Injectable } from '@angular/core';
import { Router, RoutesRecognized } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { filter, pairwise } from 'rxjs/operators';
import { Location } from '@angular/common';

@Injectable()
export class RouteEventsService {

    // save the previous route
  public previousRoutePath = new BehaviorSubject<string>('');

  constructor(
    private router: Router,
    private location: Location
  ) {

    // ..initial prvious route will be the current path for now
    this.previousRoutePath.next(this.location.path());


    // on every route change take the two events of two routes changed(using pairwise)
    // and save the old one in a behavious subject to access it in another component
    // we can use if another component like intro-advertise need the previous route
    // because he need to redirect the user to where he did came from.
    this.router.events.pipe(
      filter(e => e instanceof RoutesRecognized),
      pairwise(),
        )
    .subscribe((event: any[]) => {
        this.previousRoutePath.next(event[0].urlAfterRedirects);
    });

  }
}

hizmeti app.module'da sağla

  providers: [
    ....
    RouteEventsService,
    ....
  ]

App.component'e enjekte edin

  constructor(
    private routeEventsService: RouteEventsService
  )

son olarak istediğiniz bileşende kaydedilen önceki rotayı kullanın

  onSkipHandler(){
    // navigate the user to where he did came from
    this.router.navigate([this.routeEventsService.previousRoutePath.value]);
  }

Bu gerçekten iyi çalışıyor. Ama hızlı bir sorum var. Hiç abonelikten çıktın mı?
w0ns88

şöyle ekle (1) ekle -> pairwise (), take (1)). abone ol ((e: any)
Mukus

1
@Injectable({ providedIn: 'root' })Hizmeti kullanırsanız , otomatik olarak projenin kök modülüne (AppModule) yüklenir ve bu nedenle bunu app.module. Ayrıntılar için belgelere bakın. Bu cevapta
Hkidd

5

ANGULAR 7+ İÇİN

Aslında Angular 7.2'den beri önceki url'yi kaydetmek için bir hizmet kullanmaya gerek yoktur. Giriş sayfasına bağlanmadan önce son url'yi ayarlamak için durum nesnesini kullanabilirsiniz. İşte bir giriş senaryosu için bir örnek.

@Component({ ... })
class SomePageComponent {
  constructor(private router: Router) {}

  checkLogin() {
    if (!this.auth.loggedIn()) {
      this.router.navigate(['login'], { state: { redirect: this.router.url } });
    }
  }
}
@Component({...})
class LoginComponent {
  constructor(private router: Router) {}

  backToPreviousPage() {
    const { redirect } = window.history.state;

    this.router.navigateByUrl(redirect || '/homepage');
  }
}
----------------

Ek olarak, şablondaki verileri de iletebilirsiniz:

@Component({
  template: '<a routerLink="/some-route" [state]="{ redirect: router.url}">Go to some route</a>'
})
class SomePageComponent {
  constructor(public router: Router) {}
}

3

@ GünterZöchbauer de bunu yerel depoda saklayabilirsiniz ama ben tercih etmiyorum) serviste tasarruf etmek ve bu değeri oradan almak daha iyi

 constructor(
        private router: Router
      ) {
        this.router.events
          .subscribe((event) => {
            if (event instanceof NavigationEnd) {
              localStorage.setItem('previousUrl', event.url);
            }
          });
      }

3

Konum'u burada belirtildiği gibi kullanabilirsiniz .

Bağlantı yeni sekmede açılırsa işte kodum

navBack() {
    let cur_path = this.location.path();
    this.location.back();
    if (cur_path === this.location.path())
     this.router.navigate(['/default-route']);    
  }

Gerekli ithalatlar

import { Router } from '@angular/router';
import { Location } from '@angular/common';

0

previousNavigationNesne kullanarak oldukça basit :

this.router.events
  .pipe(
    filter(e => e instanceof NavigationEnd && this.router.getCurrentNavigation().previousNavigation),
    map(() => this.router.getCurrentNavigation().previousNavigation.finalUrl.toString()),
  )
  .subscribe(previousUrl => {}); 

0

Bir korumanın içindeki önceki URL'ye erişmek için biraz zorlandım.
Özel bir çözüm uygulamadan, bu benim için çalışıyor.

public constructor(private readonly router: Router) {
};

public ngOnInit() {
   this.router.getCurrentNavigation().previousNavigation.initialUrl.toString();
}

İlk url, önceki url sayfası olacaktır.



-2

Rxjx'ten ikili kullanarak bunu daha kolay başarabilirsiniz. "rxjs / operators" dan {filter, pairwise} içe aktar;

previousUrl: string;
constructor(router: Router) {
router.events
  .pipe(filter((evt: any) => evt instanceof RoutesRecognized), pairwise())
  .subscribe((events: RoutesRecognized[]) => {
  console.log('previous url', events[0].urlAfterRedirects);
  console.log('current url', events[1].urlAfterRedirects);
  this.previousUrl = events[0].urlAfterRedirects;
});

}


-6

Önceki sayfaya dönmek istediğimde de benzer bir sorun yaşadım. Çözüm hayal edebileceğimden daha kolaydı.

<button [routerLink]="['../']">
   Back
</button>

Ve ana url'ye geri döner. Umarım birine yardımcı olur;)


Bu işe yaramayacak, OP'nin belirttiği gibi önceki url yerine yönlendiricinin yolunda ilerlemenizi söylüyorsunuz.
Frederic Yesid Peña Sánchez

URL'niz parametrelerle karmaşıksa veya ana yolla aynı yola sahip değilse bu işe yaramaz. Yalnızca "bir şey / ebeveyn / çocuk" dan "bir şey / ebeveyn" e dönmek istiyorsanız çalışır.
A. El Idrissi
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.