[Angular] 저장되지 않은 파일이 있는데 뒤로 가기를 누른 경우 경고 알럿 띄우기
안녕하세요. 명동섞어찌개 입니다.
오늘은 Angular 페이지에서 문서 (form) 작성 중 또는 무언가를 등록하다가, 저장하지 않고 브라우저 뒤로가기 버튼을 눌렀을 때 '저장하지 않은 파일이 있습니다. 페이지를 나가시겠습니까?'라고 묻는 알럿 띄우는 기능을 만들려고 합니다.
일반적으로 이런 기능은 javascript 에서는 popstate 이벤트 리스너를 사용해서 구현합니다. (모바일에서도 사용한 기억이 있습니다.)
하지만 Angular 에서 window:popstate 로 아무리 구현해 봐도 원하는 기능이 작동하지를 않더군요.
아마도 popstate 는 페이지가 이동할 때 호출되는 이벤트인데, Angular 는 SPA(Single Page Application) 다 보니 하나의 페이지 안에서 component 끼리 routing 될 뿐이라서 저 이벤트가 호출되지 않는 듯 했습니다. (자세히 아시는 분은 댓글로 제보 부탁드립니다!!)
검색해보니 Angular 자체적으로 페이지를 나갈 때 처리해줄 수 있는 솔루션이 있더라구요.
router 의 canDeactivate !!!
canActivate 는 로그인하지 않은 사용자가 해당 페이지에 접근하지 못하게 막는 용도로 사용되는 경우를 많이 봤는데요, 페이지를 나갈 때 체크하는 용도로 canDeactivate 를 사용해 본 건 처음이었습니다.
시나리오를 말씀드리자면
1. CdnRegisterComponent 라는 페이지 컴포넌트에서 파일을 등록하다가 저장 버튼을 안 누르고
2. 브라우저 뒤로가기 버튼을 눌렀다!
이 경우에 알럿이 뜨게 하는 처리입니다.
1. CdnRegisterComponent 페이지에 저장될 파일이 있는지 없는지 판단할 flag 를 설정합니다.
이 flag 는 public 이어야 합니다. 다른 service 에서 접근이 가능해야 하거든요!
2. 페이지를 떠날 때 감시하는(?) canDeactivate Service 를 만들어줍니다.
참조: https://angular.io/api/router/CanDeactivate
3. 해당 페이지가 세팅되어 있는 있는 router 에 canDeactivate 를 세팅해줍니다.
먼저 providers 에 해당 HasUnsavedDataGuard Service 를 세팅해주고,
해당 페이지 router 에 canDeactivate 를 세팅해줍니다.
이렇게 해서 기능이 완성되었습니다!!
이외에 canDeactivate 를 사용하는 다른 용도가 있다면 댓글로 공유 부탁드립니다~^^
오늘은 Angular 페이지에서 문서 (form) 작성 중 또는 무언가를 등록하다가, 저장하지 않고 브라우저 뒤로가기 버튼을 눌렀을 때 '저장하지 않은 파일이 있습니다. 페이지를 나가시겠습니까?'라고 묻는 알럿 띄우는 기능을 만들려고 합니다.
일반적으로 이런 기능은 javascript 에서는 popstate 이벤트 리스너를 사용해서 구현합니다. (모바일에서도 사용한 기억이 있습니다.)
1 2 3 | window.addEventListener('popstate', (event) => { console.log("location: " + document.location + ", state: " + JSON.stringify(event.state)); }); |
하지만 Angular 에서 window:popstate 로 아무리 구현해 봐도 원하는 기능이 작동하지를 않더군요.
아마도 popstate 는 페이지가 이동할 때 호출되는 이벤트인데, Angular 는 SPA(Single Page Application) 다 보니 하나의 페이지 안에서 component 끼리 routing 될 뿐이라서 저 이벤트가 호출되지 않는 듯 했습니다. (자세히 아시는 분은 댓글로 제보 부탁드립니다!!)
검색해보니 Angular 자체적으로 페이지를 나갈 때 처리해줄 수 있는 솔루션이 있더라구요.
router 의 canDeactivate !!!
canActivate 는 로그인하지 않은 사용자가 해당 페이지에 접근하지 못하게 막는 용도로 사용되는 경우를 많이 봤는데요, 페이지를 나갈 때 체크하는 용도로 canDeactivate 를 사용해 본 건 처음이었습니다.
시나리오를 말씀드리자면
1. CdnRegisterComponent 라는 페이지 컴포넌트에서 파일을 등록하다가 저장 버튼을 안 누르고
2. 브라우저 뒤로가기 버튼을 눌렀다!
이 경우에 알럿이 뜨게 하는 처리입니다.
1. CdnRegisterComponent 페이지에 저장될 파일이 있는지 없는지 판단할 flag 를 설정합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Component({ selector: 'app-cdn-register', templateUrl: './cdn-register.component.html', styleUrls: ['./cdn-register.component.scss'] }) export class CdnRegisterComponent implements OnInit { . . public hasUnsavedData = false; . . fileHandling( files ) { //파일이 들어온 경우 hasUnsavedData 가 있다고 표시해준다 this.hasUnsavedData = true; } |
이 flag 는 public 이어야 합니다. 다른 service 에서 접근이 가능해야 하거든요!
2. 페이지를 떠날 때 감시하는(?) canDeactivate Service 를 만들어줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import {Injectable} from '@angular/core'; import {ActivatedRouteSnapshot, CanDeactivate, RouterStateSnapshot, UrlTree} from '@angular/router'; import {Observable} from 'rxjs'; import {CdnRegisterComponent} from '../../pages/cdn/cdn-register/cdn-register.component'; @Injectable() export class HasUnsavedDataGuard implements CanDeactivate<CdnRegisterComponent> { constructor() {} canDeactivate( component: CdnRegisterComponent, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState: RouterStateSnapshot ): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree {
|
참조: https://angular.io/api/router/CanDeactivate
3. 해당 페이지가 세팅되어 있는 있는 router 에 canDeactivate 를 세팅해줍니다.
먼저 providers 에 해당 HasUnsavedDataGuard Service 를 세팅해주고,
1 2 3 4 5 6 7 | @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], providers: [HasUnsavedDataGuard] }) export class PagesRouterModule { } |
해당 페이지 router 에 canDeactivate 를 세팅해줍니다.
1 | {path: 'cdn/register', component: CdnRegisterComponent, canDeactivate: [HasUnsavedDataGuard] }, |
이렇게 해서 기능이 완성되었습니다!!
이외에 canDeactivate 를 사용하는 다른 용도가 있다면 댓글로 공유 부탁드립니다~^^
댓글
댓글 쓰기