ionViewWillEnter & cross-tab navigation

When I first started writing web apps, lifecycle events were my life raft in a sea of uncertainty. I spent hours debug printing which ones got called when and in what order, frantically looking for some way to wrest control of the CPU back to its rightful owner: ME.

That didn’t go so well for me. See this post, which while it’s nominally about the precise combination you’re struggling with here (ionViewWillEnter and tabs), is more about deciding to accept and even embrace the limitations inherent in certain design decisions.

In this case, those design decisions surround lifecycle events and tabs. I now deal with lifecycle events only when they are the only way to work around other inherent limitations: for example, ngOnChanges is the first, if not only, place I can rely on @Input properties being properly bound. ngAfterViewInit is the first place I can rely on @ViewChild being populated.

Tabs are a seductive UI option, but very easily abused, and I think that’s happening here. I would argue that the reason you’re having trouble wiring up cross-tab interaction is tabs should be independent of one another. They’re literally modeled on old-school paper filing systems involving folders. Say you’re a lawyer, and you ask for the FrobozzCo file. It comes to your desk. You take out a bunch of papers, shuffle them around, add some more, throw some away, then you put the file back in the drawer. Nothing that you did to anything in the FrobozzCo folder affected the contents of any other folder.

With that groundwork having been laid, here’s how I would answer your questions:

  1. The “right” way to pass complex objects in my opinion is via Observables exposed by service providers that are injected wherever needed. Usually they are backed by Subjects, but that’s not required.

  2. None. This isn’t a lifecycle situation. I would have a service provider that looks like so:

class QuizService {
  activeQuestion$ = new BehaviorSubject<Question | undefined>(undefined);
  watchActiveQuestion(): Observable<Question | undefined> { return this.activeQuestion$; }
  peekActiveQuestion(): Question | undefined { return this.activeQuestion$.value; }
  pokeActiveQuestion(q: Question) { this.activeQuestion$.next(q); }
}

I would have my quiz component listen to watchActiveQuestion and react accordingly. As for the hook to call pokeActiveQuestion, …

  1. None of this matters, because I wouldn’t do this as tabs. I would make History and Quiz completely distinct pages. The click on your “old question” from the History page can call pokeActiveQuestion and (if desired) tell the router to move to the Quiz page.
1 Like