0

Asking this question for understanding: I have this code:

export class TpaEditGuard implements CanDeactivate<ResultContainerComponent> {
public editMode: boolean;
public bsModalRef: BsModalRef;
constructor(
private injector: Injector,
private modalService: BsModalService
) {   }
public canDeactivate(
target: ResultContainerComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState: RouterStateSnapshot): Observable<boolean> | boolean {

 target.hasChanges().subscribe((value) => {
  this.editMode = value;
 });

 if (this.editMode) {
  let subject = new Subject<any>();
  this.bsModalRef = this.modalService.show(NavigateConfirmComponent,
    { animated: true, keyboard: false, backdrop: false, ignoreBackdropClick: true }
  );
  this.bsModalRef.content.navEvent = subject;
  return this.bsModalRef.content.shouldNavigate();
 } else {
  return true;
 }
}

Now, the if(this.editMode... is after and outside of the .subscribe. According to synchronous flow, the if should be evaluated before the value of this.editmode gets asynchronously set and evaluate to false. But the code works! Both ways. The if evaluates to true if I am sending an observable of true from hasChanges asynchronously and the dialog box appears! I am not setting this.editMode to true anywhere earlier. How does this work? In any other situation if we had a subscription and synchronous code using a value from the subscription outside we would not have got it. For example this:

this.someService.getData().subscribe(data => this.source = data)
console.log(this.source)

Here, the value of this.source printed would not have been the value of data from the db/back-end/resource call. It would have printed undefined or whatever was set earlier. How does that asynchrony work synchronously in canDeactivate then?

A reasoning seems to have been provided in this question here when the questioner says "Since the value this.savingState in the guard is always subscribed I don't think there is an issue with the conditional goes below.". But I don't get that. What is always subscribed? What, then, is not always subscribed? Or, what are we doing special to make it always subscribed? Again, my question how is this different from the getData example?

  • You need to set this.editMode default to false. target.hasChanges is getting trigged initially. better put a console.log(value) inside subscribe(). – Suresh Kumar Ariya Aug 24 '18 at 08:43
  • I don't need it false. Code is already working the way I need it to work. I am just not understanding how that is. How is target.hasChanges getting triggered initially? – Upasana Sengupta Aug 24 '18 at 09:04
  • It's not. You're assuming it is. Services are singletons, and you're subscribing to an observable : you probably streamed a result elsewhere, resulting in your service setting the value of your variable to true. –  Aug 24 '18 at 09:06
  • But if you REALLY think the issue is what you're saying, then please, make a [mcve] to reproduce it. –  Aug 24 '18 at 09:07
  • What's not? target.hasChanges getting triggerred initially? I'm not even assuming it is. i was just asking the last commentor. Service is also setting variable to false (when in component called 'target' I've emitted false). But it should set variable to false after I've subscribed, right? So, code should move to evaluation of if before async op is completed right. But false (or true) is evaluating correctly. And yes, I have streamed a result elsewhere. – Upasana Sengupta Aug 24 '18 at 10:59

0 Answers0