moonStory

Anglar canDeactivate (라우터 이동 제어하기) 본문

Angular

Anglar canDeactivate (라우터 이동 제어하기)

moonStory_ 2023. 8. 5. 19:42
반응형

웹프로젝트 작업을 진행하던 중 데이터를 저장할 때 한 페이지에서 완료 버튼을 눌러 저장하는 방식이 아닌

[다음] -> [다음] -> [다음] 버튼을 눌러서 데이터를 작성하고 마지막 페이지에서 [저장] 하는 방식의 기획이 있었다.

 

그런 방식의 문제점이 사용자가 뒤로가기를 할 경우에 이전 페이지에서 input에 입력했던 데이터가 사라진다는 것이였다.

특정 프로세스를 진행 중이거나 보기에 저장되지 않은 변경 사항이 있을 때 다른 페이지로 이동을 할 때 이동하기 전에 진행 중인 프로세스가 취소되거나 진행할 경우 변경 사항이 삭제된다는 사실을 사용자에게 알려야 한다.

이 문제를 해결하기 위해 뒤로가기 이벤트가 발생할 경우 '이 페이지를 나갈 경우에 입력한 데이터가 삭제되고 첫 페이지로 이동합니다.' 라는 안내 메시지의 알럿창이 필요했다.

 

첫번째로 생각한 방식은 

window.addEventListener('popstate', function(event) {
  // 뒤로가기 동작이 감지되었을 때 실행되는 코드
  console.log('뒤로가기 버튼이 눌렸거나 history가 변경되었습니다.');
});

addEventListener로 뒤로가기 이벤트가 발생되는 시점을 찾자! 였다.

뒤로가기 이벤트가 발생 됐을 때 알럿 창을 띄울 수 있었지만, 페이지가 뒤로 이동하는 걸 막지는 못했다. (짧은 생각이였다..)

 

구글 검색을 해본 결과, 우리가 로그인을 할 때 authGuard를 만드는 것 처럼 routerGuard를 만들어서 특정 페이지에 가드를 넣으면 그 페이지에서는 사용자의 라우터 이동을 제어할 수 있다는 것이다.

 

 

 

 

canDeactivate라는 것을 사용할건데 이것은 Augular에서 제공하는 라우터 모듈이다. 이 인터페이스는 사용자가 특정 경로를 이동하려 할 때 이동 할 수 있는지 여부를 제어하는 가드를 제공한다. 이를 사용하여 사용자가 실수로 페이지를 떠나거나 변경 사항을 저장하지 않고 데이터를 잃지 않도록 방지할 수 있다. 

 

먼저 guard.ts를 만든다.

 

import { CanDeactivate } from '@angular/router';

export interface CanComponentDeactivate {
  canDeactivate: () => boolean | Promise<boolean> | Observable<boolean>;
}

@Injectable()
export class PendingChangesGuard implements CanDeactivate<CanComponentDeactivate> {
  canDeactivate(
    component: CanComponentDeactivate, 
    currentRoute: ActivatedRouteSnapshot,
    currentState: RouterStateSnapshot,   //현재 페이지 라우터 url
    nextState?: RouterStateSnapshot      //이동할 페이지 라우터 url
  ): boolean | Promise<boolean> | Observable<boolean> {
    return component.canDeactivate ? component.canDeactivate() : true;
  }
}

현재 라우터 상태와 이동할 라우터 상태를 모두 알 수 있기 때문에 사용하기가 편했다.

알럿 작업은 밑에 계속 currentState나 nextState를 사용하여 작업하면 된다.

 

routing.module에 가드를 등록한다.
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PendingChangesGuard } from './pending-changes.guard';

const routes: Routes = [
  // ... 다른 라우트 설정 ...
  {
    path: 'your-component-path',
    component: YourComponent,
    canDeactivate: [PendingChangesGuard] // 여기에 등록 (사용할 가드네임)
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
  providers: [PendingChangesGuard] // 여기에 등록 (사용할 가드네임)
})

이렇게 가드를 만들어서 사용할 라우트에 canDeactivate로 가드를 등록하게 되면 해당 라우트에서 라우팅 이동을 제어할 수 있게 된다.

반응형