I have a page that has a form that checks if the user has unsaved changes before navigating away from it.
The problem is that even with a preventDefault() and return false, the user is still able to click away from the component.
Is there a way to prevent the ngOnDestroy or click event from happening?
Note: User is not going to a different route, just another tab from the same component.
ngOnDestroy() {
if (this.myForm.dirty) {
let save = confirm('You are about to leave the page with unsaved changes. Do you want to continue?');
if (!save) {
window.event.preventDefault();
return false;
}
}
}
I have a page that has a form that checks if the user has unsaved changes before navigating away from it.
The problem is that even with a preventDefault() and return false, the user is still able to click away from the component.
Is there a way to prevent the ngOnDestroy or click event from happening?
Note: User is not going to a different route, just another tab from the same component.
ngOnDestroy() {
if (this.myForm.dirty) {
let save = confirm('You are about to leave the page with unsaved changes. Do you want to continue?');
if (!save) {
window.event.preventDefault();
return false;
}
}
}
Share
Improve this question
edited Jul 11, 2017 at 7:09
Akkusativobjekt
2,0231 gold badge21 silver badges26 bronze badges
asked Jul 11, 2017 at 7:06
francofranco
6974 gold badges8 silver badges21 bronze badges
7
- you can just disable the button which navigate away without saving changes. ngOnDestroy is not a guard that prevent destroying from happening, it just do some logic before destroying the component, such as unsubscribing for observables or close files...etc. – Raed Khalaf Commented Jul 11, 2017 at 7:09
- you may be looking for auth guards. – user663031 Commented Jul 11, 2017 at 7:10
- @torazaburo I know guards only work with routes. I noted that the user is still in the same route but clicking to a different tab. – franco Commented Jul 11, 2017 at 7:14
- @RaedKhalaf I don't think disabling navigation buttons look good visually. I would rather give the user the option to proceed if they wanted to. – franco Commented Jul 11, 2017 at 7:16
- ok, then don't disable it, when the user click the button which navigate away without saving, just add ' discard = confirm("Do you want to discard changes") ', if discard is true navigate away, other don't navigate away. – Raed Khalaf Commented Jul 11, 2017 at 7:18
2 Answers
Reset to default 12You would wanna use CanDeactivate guard.
Here is an example:
1. Create a guard service/provider.
import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs/Observable';
export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
@Injectable()
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate) {
return component.canDeactivate ? component.canDeactivate() : true;
}
}
2. Add your guard service (CanDeactivateGuard) in your app.module providers
providers: [
CanDeactivateGuard,
]
3. Update your routing, to something like this:
{
path: "pipeline/:id",
component: OnePipelineComponent,
canDeactivate: [CanDeactivateGuard],
},
4. Implement canDeactivate
method in your component where you want to prevent ngOnDestroy. In my case, it was OnePipelineComponent
as mentioned in the route above.
canDeactivate() {
console.log('i am navigating away');
// you logic goes here, whatever that may be
// and it must return either True or False
if (this.user.name !== this.editName) {
return window.confirm('Discard changes?');
}
return true;
}
Note: Follow steps 1 & 2 only once, obviously, & just repeat steps 3 & 4 for every other component where you want the same behaviour, meaning, to prevent ngOnDestroy or to do something before a component can be destroyed).
Check out these articles for code sample & an explanation for the code written above. CanDeactivate & CanDeactivate Guard Example
You are mixing two concepts - navigating away means to a new route. The correct angular solution to this is implementing a CanDeactivateGuard. The docs on that are here.
A stack overflow question with answers is here.
In your situation the user is not navigating to a new page (ie. the route does not change). They are simply clicking on a new tab.
Without seeing more code, it's hard to know if both tabs are part of the same form or in two different forms.
But regardless, you need a click handler on the other tab button and in THAT click handler you need to check if the data for the current tab is unsaved (ie. if that tab is one single form, is that form dirty?).
So basically move the code you posted from ngOnDestroy
and into that click handler.