Reputation: 433
I have two tabs (PrimeNg Tabview) in my Angular4 page with many input fields like textboxes, textareas, dropdowns etc. I also have a side menu-bar to navigate to other pages within the application. I want if there is any changes in the data in the in those input fields then there will be a pop-up message (a modal or a confirmation box) if user tries to change the tab, or to navigate to other pages using the side menu-bar.
I have tried the ngOnDestroy()
method. Though this method gets triggered only when the page is getting closed (by navigating to other page or move to next tab-page) but it is not allowing you show a modal/confirmation box from within the method because it is on destroy life cycle hook.
Please help me to identify the actual event using which I can prompt user with a confirmation box if changes are there in any of the input fields in the page/form.
@surjit Suggestion:
my-guard.service.ts:
export interface CanComponentDeactivate {
CanDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
@Injectable()
export class CreateRequestGuardService implements CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate) {
let vDeactivate = component.CanDeactivate ? component.CanDeactivate() : true;
return vDeactivate;
}
}
Inside my-component.ts:
import { CreateRequestGuardService } from './my-guard.service';
canDeactivate(): Observable<boolean> | boolean {
console.log('I am moving away!');
if (!this.isSaved) {
const confirmation = window.confirm('Are you sure?');
return Observable.of(confirmation);
}
else{
return true;
}
}
In my-router.ts:
import { CreateRequestGuardService } from './my-guard.service';
const allRoutes: Routes = [
{ path: 'save', component: my-component, canDeactivate: [MyGuardService]},
{ path ....},
..
]
Upvotes: 3
Views: 7830
Reputation: 348
Use CanDeactivate
guard in the component route which you want to protect
Read CanDeactivate for more information
my-guard.service.ts:
export interface CanComponentDeactivate {
CanDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
@Injectable()
export class CreateRequestGuardService implements CanDeactivate<CanComponentDeactivate> {
canDeactivate(component: CanComponentDeactivate,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState?: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
return component.canDeactivate(); //the function will be called on the component, that's why we'll implement the function on the component.
}
}
my-router.ts:
import { CreateRequestGuardService } from './my-guard.service'; //the class name in my-guard.service.ts
const allRoutes: Routes = [
{ path: 'save', component: myComponent, canDeactivate: [CreateRequestGuardService]},
{ path ....},
..
]
my-component.ts
import { CreateRequestGuardService } from './my-guard.service';
export class myComponent implements CanComponentDeactivate { //implements the interface created on the guard service
/*
your component data
*/
//implementation of canDeactivate
canDeactivate(): Observable<boolean> | Promise<boolean> | boolean {
if(form_is_edited && not_saved){
return confirm("Discard Changes?");
}
else
return true;
}
}
NOTE : Also don't forget to add the guard service(class) to the providers
array in the app.module.ts
file.
Upvotes: 6