I am attempting to use a CanDeactivate guard to detect when a user navigates away from the component. The purpose is to #1 check if the current user owns the 'Is Being Edited' lock on the record, and #2 if so, call an observable to update the database.
The code I have is partially working, but there is a race condition where the lock isn't always released, probably because the subscription to this.updateIsBeingEdited$(false)
doesn't always complete by the time the next return statement is called. So I know this isn't implemented correctly.
How can I make it such that the this.updateIsBeingEdited$
observable completes before the canDeactivate returns a value?
The return value should always be true, because the component should always deactivate, it just need to make sure this.updateIsBeingEdited$.subscribe()
is done before deactivation completes.
COMPONENT
canDeactivate(): Observable<boolean> | boolean {
// Check if Is Being Edited must be removed
if (this.mustReleaseIsBeingEdited()) {
this.removeIsBeingEditedSub = this.updateIsBeingEdited$(false).subscribe(result => {
// QUESTION: How to wait until this is complete before allowing component to deactivate?
return true;
}, err => { console.error(err); }, () => { });
// Always allow deactivation
return true;
} else {
return true;
}
}
private updateIsBeingEdited$(isBeingEdited): Observable<boolean> {
const editedObj = {
_id: this.record._id,
IsBeingEdited: isBeingEdited,
EditedBy: this.accessLevelService.getUserId()
}
return this.httpService!.postData$(
`records/_id/${editedObj._id}/IsBeingEdited/`,
editedObj
);
}
GUARD
export interface ComponentCanDeactivate {
canDeactivate: () => boolean | Observable<boolean>;
}
/**
* Guard to notify client that user has navigated away from route
* Implemented in component for managing record locks only
*/
@Injectable({
providedIn: 'root'
})
export class RecordLocksGuard implements CanDeactivate<ComponentCanDeactivate> {
canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
if (!component) {
return true;
}
component.canDeactivate();
// Always allow component to deactivate
return true;
}
}