I am trying to implement deactivate guard in standalone angular components which to opens material dialog for confirm/cancel and to work in both – ts route change and browser back button.
I am trying to implement the can deactivate guard in angular standalone components. I have exactly the same implementation with a project which is with standard components and it works. This is the code of my can deactivate guard:
import { inject } from '@angular/core';
import { ActivatedRouteSnapshot, CanDeactivateFn, RouterStateSnapshot } from '@angular/router';
import { MatDialog} from '@angular/material/dialog';
import { MxDialogComponent } from '../../mx/dialog';
import { TranslocoService } from '@ngneat/transloco';
import { CanComponentDeactivate } from '../../interfaces/can-component-deactivate.interface';
export const canComponentDeactivateGuard: CanDeactivateFn<CanComponentDeactivate> = (
component: CanComponentDeactivate,
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) => {
const translocoService: TranslocoService = inject(TranslocoService);
const dialog: MatDialog = inject(MatDialog);
if (component.canDeactivate && component.canDeactivate()) {
return true;
}
let message = translocoService.translate('discardDialog.message');
let cancelAction = translocoService.translate('common.dialogs.discardDialog.cancelAction');
const dialogRef = dialog.open(MxDialogComponent , {
autoFocus: false,
disableClose: true,
restoreFocus: false,
width: '620px'
});
dialogRef.componentInstance.title = translocoService.translate('common.dialogs.discardDialog.title');
dialogRef.componentInstance.messageBottom = message;
dialogRef.componentInstance.confirmActions = [
{ text: translocoService.translate('common.dialogs.discardDialog.confirmAction'), value: true, dataAttr: 'cx-dialog-confirm' }
];
dialogRef.componentInstance.cancelActions = [
{ text: cancelAction, value: false, dataAttr: 'cx-dialog-cancel' }
];
return dialogRef.afterClosed();
// return window.confirm('Do you really want to cancel?');
};
In my standalone component i have implemented the
...
export class MyStandaloneComponent implements OnInit, OnDestroy, CanComponentDeactivate
....
canDeactivate(): boolean {
return !this.myHelperService.hasChanges;
}
here is the interface for the CanComponentDeactivate
import { Observable } from 'rxjs';
export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
i have also set in the routes file of the standalone component:
canDeactivate: [canComponentDeactivateGuard],
runGuardsAndResolvers: 'paramsOrQueryParamsChange',
Now if i try to naviage manually via typescript like:
this.router.navigateByUrl('/home');
The dialog is opened and working with both cancel and confirm. When i press the browser back button the code again runs including the code in the whole guard can deactivate but i end up going to the home page and the dialog is not even being shown. This scenario with this code is working fine when the component is not standalone. I have tried opening standard window confirm
return window.confirm('Do you really want to cancel?');
in the end of the guard instead of the mat dialog and it is working but when i try it with material dialog it is not.
subradeep chandarma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.