[Angular2 Router] CanDeactivate Route Guard - How To Confirm If The User Wants To Exit A Route

In this tutorial we are going to learn how we can to configure an exit guard in the Angular 2 Router. We are going to learn how to use a CanDeactivate route guard to ask the user if he really wants to exist the screen, giving the user to for example save data that was not yet persisted.

What ‘canDeactivate‘ do is for example, you are editing a form, and you click other page by mistake, system will show a confirm dialog to ask whether you want to stay this page.

So first, add input box in hero component, when you type something and press enter, will edit the ‘editing‘ variable to ‘true‘, then we use this variable to control.

import {
  Component,
  OnInit,
  OnDestroy,
  ViewChild,
} from ‘@angular/core‘;
import {ActivatedRoute, Router} from "@angular/router";
import {StarWarsService} from "../heros.service";
import {Observable, Subscription} from "rxjs";

@Component({
  selector: ‘app-hero‘,
  templateUrl: ‘hero.component.html‘,
  styleUrls: [‘hero.component.css‘]
})
export class HeroComponent implements OnInit, OnDestroy {

  @ViewChild(‘inpRef‘) input;

  heroId: number;
  hero: Observable<any>;
  description: string;
  querySub: Subscription;
  editing: boolean = false;

  constructor(private route: ActivatedRoute,
              private router: Router,
              private starwarService: StarWarsService) {
  }

  ngOnInit() {
    this.hero = this.route.params
     .map((p:any) => {
      this.editing = false;
      this.heroId = p.id;
      return p.id;
     })
     .switchMap( id => this.starwarService.getPersonDetail(id));

   /* // since herocomponent get init everytime, it would be better to use snapshot for proferemence
    this.heroId = this.route.snapshot.params[‘id‘];
    this.hero = this.starwarService.getPersonDetail(this.heroId);*/

    this.querySub = this.route.queryParams.subscribe(
      param => this.description = param[‘description‘]
    );

    console.log("observers", this.route.queryParams[‘observers‘].length)
  }

  ngOnDestroy() {
    this.querySub.unsubscribe()
  }

  saveHero(newName){
    this.editing = true;
    console.log("editing", this.editing)
  }

  prev(){
    return Number(this.heroId) - 1;
  }

  next(){
    return Number(this.heroId) + 1;
  }
}

Because now, from our hero compoennt, we can navigate to other hero component, so snapshot is not ideal for this case, we need to use router.params.

<div>
  <h2>{{description}}: {{(hero | async)?.name}}</h2>
  <div>
    <a [routerLink]="[‘/heros‘, prev()]">Previous</a>
    <a [routerLink]="[‘/heros‘, next()]">Next</a>
  </div>
  <div>
    <input type="text" #inpRef (keyup.enter)="saveHero(inpRef.value)">
  </div>
  <br>
  <img src="{{(hero | async)?.image}}" alt="">
  <div>
    <a [routerLink]="[‘/heros‘]">Back</a>
  </div>
</div>

CanDeactivateHero.ts:

import {CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot} from "@angular/router";
import {Observable} from "rxjs";
import {HeroComponent} from "./hero/hero.component";
export class CanHeroDeactivate implements CanDeactivate<HeroComponent>{
  canDeactivate(component: HeroComponent,
                route: ActivatedRouteSnapshot,
                state: RouterStateSnapshot): Observable<boolean>|boolean {

    if(!component.editing){
      return true;
    }

    return confirm(‘You have unsaved message, are you sure to leave the page?‘)
  }

}

Heros.router.ts:

import {HerosComponent} from "./heros.component";
import {RouterModule} from "@angular/router";
import {HeroComponent} from "./hero/hero.component";
import {CanHeroDeactivate} from "./CanDeactiveHero.directive";
const routes = [
  {path: ‘‘, component: HerosComponent},
  {path: ‘:id‘, component: HeroComponent, canDeactivate: [CanHeroDeactivate]},
];
export default RouterModule.forChild(routes)

heros.module.ts:

import { NgModule } from ‘@angular/core‘;
import { CommonModule } from ‘@angular/common‘;
import { HerosComponent } from ‘./heros.component‘;
import herosRoutes from ‘./heros.routes‘;
import {HeroComponent} from "./hero/hero.component";
import {StarWarsService} from "./heros.service";
import {RouterModule} from "@angular/router";
import {CanHeroDeactivate} from "./CanDeactiveHero.directive";

@NgModule({
  imports: [
    CommonModule,
    herosRoutes
  ],
  declarations: [HerosComponent, HeroComponent],
  providers: [StarWarsService, CanHeroDeactivate]
})
export default class HerosModule { }

Github

时间: 2024-10-21 17:42:09

[Angular2 Router] CanDeactivate Route Guard - How To Confirm If The User Wants To Exit A Route的相关文章

[Angular2 Router] CanActivate Route Guard - An Example of An Asynchronous Route Guard

In this tutorial we are going to learn how we can to configure an can activate route guard in the Angular 2 router. We are going to implement the concrete example where a user can only enter a certain route if its authorized to do so. We are also goi

[Angular2 Router] Resolving route data in Angular 2

From Article: RESOLVING ROUTE DATA IN ANGULAR 2 Github If you know Anuglar UI router, you must know resolve function in ui router, which you can load data before template and controller get inited. In Angular2 router, you can also use resovler. The r

[Angular2 Router] Optional Route Query Parameters - The queryParams Directive and the Query Parameters Observable

In this tutorial we are going to learn how to use the Angular 2 router to pass optional query parameters from one route into another route. There are couple of ways of doing this from the source route perspective: we use the queryParams property in t

[Angular2 Router] Exiting an Angular 2 Route - How To Prevent Memory Leaks

In this tutorial we are going to learn how we can accidentally creating memory leaks in our application while using the Angular 2 router. We are going to learn how we can prove that the memory leak is happening, we are going to learn what is causing

Angular2 Router

1 import Router import {RouteConfig, RouterOutlet, RouterLink, routerInjectables} from 'angular2/router'; 2 setting your RouteConfig @RouteConfig([ {path: '/', component: List, as: 'list'}, {path: '/about', component: Add, as: 'add'}, {path: '/help',

[Angular2 Router] Configuring a Home Route and Fallback Route - Learn An Essential Routing Concept

In this tutorial we are going to learn how to configure the Angular 2 router to cover some commonly used routing scenarios: what if the user goes to the root of the application manually ? Probably you would want some sort of home page to be displayed

[Angular2 Router] Guard: CanLoad

'canLoad' guard can decide whether a lazy load module can be loaded or not. @Injectable() export class CanLoadPokemon implements CanLoad { constructor(private authService: AuthService) { } canLoad(route: Route): Observable<boolean>|Promise<boolea

[Angular2 Router] Configure Auxiliary Routes in the Angular 2 Router - What is the Difference Towards a Primary Route?

In this tutorial we are going to learn how we can can configure redirects in the angular 2 router configuration. We are also going to see again another example on how the order of the configuration might trip us. We are going to see the different bet

[Angular2 Router] Load Data Based on Angular 2 Route Params

You can load resource based on the url using the a combination of ActivatedRouteand Angular 2’s Http service. Since the params and Http are both streams, you can use RxJS to get the data off the param then switchMap over to an Http request using that