how to implement confirm on exit in angular 4?

2019-09-20 00:02发布

问题:

I want to know how can I implement a confirm-on-exit component so that on page refresh or leaving tab or window or screen I can execute a confirm on exit method, so that if user click OK he will leave the screen and on click on NO he will remain on same screen?

Code I am using here is:

import { Component, OnInit, Input, Output, HostListener } from '@angular/core';
@Component({
    selector: 'confirmonexit',
    templateUrl: './confirm-on-exit.html' 
})
export class ConfirmOnExitComponent {
    @Input() isDirty: boolean;
    public isConfirmed: boolean = false;
    @HostListener('window:beforeunload',['$event']) beforeUnloadHander() {
        if (this.isDirty) {
            let msg: string = 'Are you sure you want to navigate without saving the entered data on the screen ? '
            if (confirm(msg)) {
                this.isDirty = false;
                this.isConfirmed = false;           
            } else {
                this.isDirty = true;
                event.preventDefault();
            }
        }
    }
}

appModule added - this component in declarations
html added =  <confirmonexit [isDirty]="CreateEditForm.form.dirty"></confirmonexit>

I don't know where the mistake is. I am not able to execute this functionality. Could anyone help me out?

回答1:

you can use angular deactivate guard on a route .This will execute as soon as you try to navigate away from any route.For example you can refer this https://scotch.io/courses/routing-angular-2-applications/candeactivate

SO if you are using a form then you can pass the form to the guard and then check for form state.if it is dirty it means it has been changed and then you can show the confirm dialog to the user



回答2:

you can add directive inside ng-form and put a property on confirm directive as below. i hope this will help you

<form name="FormName">
            <confirm-exit is-dirty="FormName.$dirty"></confirm-exit>
<form>


回答3:

You can use CanDeactivate guard that gives us the possibility to decide if we really want to navigate away from a route (for example if we want to prevent our users from losing unsaved changes when filling out a form and accidently clicking on a button to cancel the process).

The CanDeactivate guard also has access to the instance of the active component, so we can implement a hasChanges() that check if there have been changes and conditionally ask for the user confirmation before leave. In the following example the CanDeactivateComponent implements the methods hasChanges() that returns a boolean value indicating if the components has detected any changes (we can check the dirty state of the form comparing its previous model and with the current one). The implementation of CanDeactivate guard is similar to the CanActivate guard implelementaion (we can create a function, or a class that implements the CanDeactivate interface):

import { CanDeactivate } from '@angular/router';
import { CanDeactivateComponent } from './app/can-deactivate';

export class ConfirmDeactivateGuard implements CanDeactivate<CanDeactivateComponent> 
{
  canDeactivate(target: CanDeactivateComponent) 
  {
    if(target.hasChanges()){
      return window.confirm('Do you really want to cancel?');
    }
    return true;
  }
}

Even though, this is a very trivial implementation, there’s one thing that we didn’t see in the previous example. CanDeactivate uses a generic, so we need to specify what component type we want to deactivate.

We implement a method canDeactivate(), that is called by Angular’s router internally if needed.

{ 
  path: '',
  component: SomeComponent,
  canDeactivate: [ConfirmDeactivateGuard]
}

Last, like all other services on Angular, this guard needs to be registered accordingly:

@NgModule({
  ...
  providers: [
    ...
    ConfirmDeactivateGuard
  ]
})
export class AppModule {}

We can have multiple guards protecting a single route, which helps us implementing sophisticated use cases, where a chain of different checks is needed.