I have a confirm/cancel modal dialog that pops up when a user leaves a route. I do this by using a guard with the canDeactivate method. However I want canDeactivate to wait until it gets a response from the modal before returning anything.
I have tried to do this by returning an observable but it is not working.
canDeactivate(): Observable<boolean> | boolean {
if(this.isFormStarted()) {
this.formService.showExitModal(true);
return this.formService.getModalSelectionObservable();
}
else {
return true;
}
}
Nothing is happening when I click confirm even though I can see that the observable is working fine when I do a console.log inside the if block
this.formService.getModalSelectionObservable().subscribe(
value => console.log("dialog value: " + value)
);
Here is how the form service looks.
private modalConfirmation = new Subject<boolean>();
public setModalSelectionObservable(confirmLeave: boolean) {
this.modalConfirmation.next(confirmLeave);
}
public getModalSelectionObservable(): Observable<boolean> {
return this.modalConfirmation.asObservable();
}
Use take(1)
or first()
(don't forget to import)
return this.formService.getModalSelectionObservable().first();
to ensure the observable is closed after the first event, otherwise the router will wait until it is closed from the service.
It was not working on my end because I was using BehaviorSubject
with initial value null
.
Make sure to create Observable from Subject
like:
private modalConfirmation = new Subject<boolean>();
public getModalSelectionObservable(): Observable<boolean> {
return this.modalConfirmation.asObservable();
}
Just putting this here in case someone in future is as careless as me:
If your component has a function hasUnsavedChanges()
your canDeactivate()
method would need to return !hasUnsavedChanges()
.
But then if you start using an observable for hasUnsavedChanges
, you'll be returning !hasUnsavedChanges$
which will just be a falsey value.
If you need to support both you can do this:
canDeactivate(component: C)
{
var hasUnsavedChanges = component.hasUnsavedChanges();
if (typeof (hasUnsavedChanges) === 'boolean')
{
return !hasUnsavedChanges;
}
else
{
return hasUnsavedChanges.map(x => !x);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With