moonStory
Anglar canDeactivate (라우터 이동 제어하기) 본문
웹프로젝트 작업을 진행하던 중 데이터를 저장할 때 한 페이지에서 완료 버튼을 눌러 저장하는 방식이 아닌
[다음] -> [다음] -> [다음] 버튼을 눌러서 데이터를 작성하고 마지막 페이지에서 [저장] 하는 방식의 기획이 있었다.
그런 방식의 문제점이 사용자가 뒤로가기를 할 경우에 이전 페이지에서 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로 가드를 등록하게 되면 해당 라우트에서 라우팅 이동을 제어할 수 있게 된다.