Angular에서 이전 페이지 URL을 확인하는 방법은 무엇입니까?


104

현재 URL이있는 페이지에 있다고 가정합니다 /user/:id. 이제이 페이지에서 다음 페이지로 이동합니다 :id/posts.

이제 방법이 있습니까? 그러면 이전 URL이 무엇인지 확인할 수 있습니다 /user/:id.

아래는 내 경로입니다

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

답변:


83

경로 변경을 구독하고 현재 이벤트를 저장하여 다음에 발생할 때 사용할 수 있습니다.

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

Angular에서 경로 변경을 감지하는 방법을 참조하십시오 .


12
감사합니다 @ Günter 당신은 항상 내 하루를 저장합니다.
Chandra Shekhar

34
이것은 나를위한 이전 경로가 아니라 현재 경로 만 나열합니다.
데이비드 아구

2
당신이 기대하는 것에 달려 있습니다. 처음 null에는 이전 경로가 없기 때문입니다. 루트 라우터에서도이 작업을 수행해야합니다. 그렇지 않으면이 구성 요소의 하위 경로 사이를 탐색 할 때만 얻을 수 있습니다.
Günter Zöchbauer 2017

8
생성자가 처음 실행될 때 이전 URL을 제공하지 않습니다.
Ekaitz Hernandez Troyas

9
생성자가 처음 실행될 때 이전 URL로 어떤 값을 기대합니까?
Günter Zöchbauer

114

아마도 다른 모든 대답은 각도 2.X에 대한 것입니다.

이제 각도 5.X에서는 작동하지 않습니다. 나는 그것으로 일하고있다.

NavigationEnd 만 있으면 이전 URL을 가져올 수 없습니다.

라우터는 "NavigationStart", "RoutesRecognized", ..., "NavigationEnd"에서 작동하기 때문입니다.

당신은 확인할 수 있습니다

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

그러나 여전히 "NavigationStart"를 사용해도 이전 URL을 가져올 수 없습니다.

이제 pairwise를 사용해야합니다.

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

pairwise를 사용하면 어떤 URL이 시작되고 있는지 확인할 수 있습니다.

"RoutesRecognized"는 출발지에서 타겟 URL로 변경하는 단계입니다.

그래서 그것을 필터링하고 그것에서 이전 URL을 가져옵니다.

마지막으로,

이 코드를 상위 구성 요소 이상 (예 : app.component.ts)에 넣습니다.

이 코드는 라우팅을 마친 후에 실행되기 때문입니다.

각도 업데이트 6+

events.filter필터는 이벤트의 일부가 아니므로 코드를 변경 때문에 오류를 제공

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
서비스로 구현되었으며 훌륭하게 작동합니다. 각도 6.1.7을 사용하고 있습니다.
A. El Idrissi

5
@ tjvg1991 페이지를 새로 고치면 메모리 데이터가 손실되었습니다. 이전 데이터를 유지하는 경우 localStorage 또는 쿠키를 사용해야합니다. (메모리가 아닌 로컬에 데이터 저장)
진병 주

@BYUNGJUJIN 감사합니다!
john

1
의 반환 값을 저장 @BYUNGJUIN subscribe()필드 및 통화 unsubscribe()에에 ngOnDestroy(). 서버가 있어야합니다. 여기에서 구독 취소에 대한 예가 담긴 질문.
Günter Zöchbauer

1
: Google Play 무비 구독 취소이 확인하시기 바랍니다 malcontentboffin.com/2017/12/...
BYUNGJU JIN

51

주입 가능한 서비스를 만듭니다.

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

그런 다음 필요한 모든 곳에서 사용하십시오. 현재 변수를 가능한 한 빨리 저장하려면 AppModule에서 서비스를 사용해야합니다.

// 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
나는 이것이 가장 우아한 해결책이라고 생각합니다. 이 코드를 새로운 필터 및 쌍별 솔루션과 병합하십시오. stackoverflow.com/a/35287471/518879
danger89

2
추신. 다음과 같이이 RouterExtService를 apps-routing.module.ts (내 경우)에 추가하는 것을 잊지 마십시오.@NgModule({ ..., providers: [RouterExtService]}) export class AppRoutingModule { }
danger89

이 서비스 솔루션에 큰 문제가 있습니다. 제 경우 routerExtService.getPreviousUrl()에는 컴포넌트에서 사용되는 서비스의 생성자 에서 메소드를 호출합니다 . 어떤 이유로 실제 업데이트보다 일찍 호출되었습니다. 타이밍 의존성이 있다는 뜻입니다! 주제를 사용하는 것이 훨씬 쉽다고 생각합니다.
danger89

음, 작은 프로젝트에서 잘 작동했습니다. 필요에 맞게 약간의 조정이 필요할 수 있습니다. 문제를 해결 했습니까?
Juliano

현재 내 URL에 내 상태를 '저장'하기 위해 소위 URL Matrix 매개 변수 를 사용하고 있습니다. 기본적으로 브라우저 URL은 뒤로 버튼을 사용할 때 상태를 저장합니다. 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

이전 URL을 문자열로 가져 오기위한 Angular 6 업데이트 코드.

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

이것은 가드에 의해 차단 된 URL을 반환합니다. 활성화 된 이전 URL 만 가져올 수있는 방법이 있습니까 (가드에 의해 차단되지 않음)?
Exocomp

1
라우터에서 구독을 취소하는 가장 좋은 방법에 대한 힌트가 있습니까?
j4v1

공장! "NavigationEnd는"하지 작업 않는 이유를 정말 모르겠다
davidwillianx

13

이것은 각도> = 6.x 버전에서 나를 위해 일했습니다.

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

11

내가 사용하고 각도 (8) 와 프랭클린 - 경건한을 해결해 @ 문제의 답을. 제 경우에는 구독 내에서 이전 URL을 가져 오면 뷰의 일부 데이터가 첨부되면 부작용이 발생합니다.

내가 사용한 해결 방법은 경로 탐색에서 이전 URL을 선택적 매개 변수로 보내는 것입니다.

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

구성 요소에서이 값을 얻으려면 :

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

this.router 및 this.route는 각 구성 요소의 생성자 내부에 삽입되고 @ angular / router 멤버로 가져옵니다.

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

10

Angular 8 및 rxjs 6 (2019 버전)

다른 훌륭한 솔루션을 기반으로 솔루션을 공유하고 싶습니다.

먼저 경로 변경을 수신하는 서비스를 만들고 Behavior Subject에 마지막 이전 경로를 저장 한 다음 생성자의 주 app.component에이 서비스를 제공 한 다음이 서비스를 사용하여 원하는 때에 원하는 이전 경로를 가져옵니다.

사용 사례 : 사용자를 광고 페이지로 리디렉션 한 다음 사용자가 원래 있던 위치로 자동 리디렉션하므로 마지막 이전 경로가 필요합니다.

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

  }
}

app.module에서 서비스 제공

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

app.component에 삽입

  constructor(
    private routeEventsService: RouteEventsService
  )

마지막으로 원하는 구성 요소에서 저장된 이전 경로를 사용하십시오.

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

이것은 정말 잘 작동합니다. 하지만 빠른 질문이 있습니다. 구독을 취소 한 적이 있습니까?
w0ns88

add take (1) like
this-

1
@Injectable({ providedIn: 'root' })서비스 를 사용 하면 프로젝트의 루트 모듈 (AppModule)에 자동으로로드되므로 .NET Framework에 수동으로 제공 할 필요가 없습니다 app.module. 자세한 내용 은 문서 를 참조하십시오. 이 답변에
Hkidd

7

ANGULAR 7+

실제로 Angular 7.2 이후에는 이전 URL을 저장하기 위해 서비스를 사용할 필요가 없습니다. 로그인 페이지에 연결하기 전에 상태 개체를 사용하여 마지막 URL을 설정할 수 있습니다. 다음은 로그인 시나리오의 예입니다.

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

또한 템플릿의 데이터를 전달할 수도 있습니다.

@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 또한 localstorage에 저장할 수 있지만 선호하지 않습니다.) 서비스에 저장하고 거기 에서이 값을 얻는 것이 좋습니다.

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

3

언급 한대로 위치를 사용할 수 있습니다. 여기에 .

링크가 새 탭에서 열린 경우 내 코드는 다음과 같습니다.

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

필수 수입품

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

0

previousNavigation객체 를 사용하면 매우 간단 합니다.

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

0

경비원 내부에서 이전 URL에 액세스하는 데 어려움을 겪었습니다.
사용자 지정 솔루션을 구현하지 않으면이 솔루션이 저에게 효과적입니다.

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

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

초기 URL은 이전 URL 페이지가됩니다.


0

이 간단한 솔루션이 저에게 효과적이었습니다.

import 'rxjs/add/operator/pairwise';
import { Router } from '@angular/router';

export class TempComponent {
    constructor(private router: Router) {
        this.router.events.pairwise().subscribe((event) => {
            console.log(event); // NavigationEnd will have last and current visit url
        });
    };
}


-2

rxjx에서 pairwise를 사용하면이 작업을 더 쉽게 수행 할 수 있습니다. import {filter, pairwise} from 'rxjs / operators';

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

이전 페이지로 돌아가고 싶을 때 비슷한 문제가 발생했습니다. 솔루션은 제가 상상할 수있는 것보다 쉬웠습니다.

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

그리고 부모 URL로 돌아갑니다. 누군가를 도울 수 있기를 바랍니다.)


이것은 작동하지 않을 것입니다. OP가 말한 것처럼 이전 URL이 아닌 라우터의 경로로 이동하라는 것입니다.
Frederic Yesid Peña Sánchez

URL이 매개 변수로 복잡하거나 상위 경로와 동일한 경로가없는 경우에는 작동하지 않습니다. "무언가 / 부모 / 자식"에서 "무언가 / 부모"로 돌아 가려는 경우에만 작동합니다.
A. El Idrissi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.