Repository: ionic-team/ionic-framework
File: angular/src/directives/navigation/ion-router-outlet.ts (TypeScript)

Code before:
            });
         * ```
         * where `this.environmentInjector` is a provider of `EnvironmentInjector` from @angular/core.
         */
        const environmentInjector = resolverOrInjector ?? this.environmentInjector;
        cmpRef = this.activated = this.location.createComponent(component, {
          index: this.location.length,
          injector,
          environmentInjector,
        } as any);
      }
      // Once the component is created we can push it to our local subject supplied to the proxy
      component$.next(cmpRef.instance);

      // Calling `markForCheck` to make sure we will run the change detection when the
      // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
      enteringView = this.stackCtrl.createView(this.activated, activatedRoute);

      // Store references to the proxy by component
      this.proxyMap.set(cmpRef.instance, activatedRouteProxy);
      this.currentActivatedRoute$.next({ component: cmpRef.instance, activatedRoute });
    }

    this.activatedView = enteringView;

    this.navCtrl.setTopOutlet(this, this.stackCtrl.setActive(enteringView)).subscribe((stackEvent) => {
      this.activateEvents.emit(cmpRef.instance);
      this.stackEvents.emit(stackEvent);
    });
  }

  /**
   * Returns `true` if there are pages in the stack to go back.
   */
  canGoBack(deep = 1, stackId?: string): boolean {
    return this.stackCtrl.canGoBack(deep, stackId);
  }

  /**
   * Resolves to `true` if it the outlet was able to sucessfully pop the last N pages.
   */
  pop(deep = 1, stackId?: string): Promise<boolean> {
    return this.stackCtrl.pop(deep, stackId);
  }

  /**
   * Returns the URL of the active page of each stack.
   */
  getLastUrl(stackId?: string): string | undefined {
    const active = this.stackCtrl.getLastUrl(stackId);
    return active ? active.url : undefined;

Review comment (suggestion):
~ An alternative pattern here that may be more clear, is having an API like:
```ts
this.navCtrl.setTopOutlet(this, enteringView)
```

Then providing the stack controller to the nav controller, so that it can call the `setActive` method. This would cut down on passing around a promise, which is an uncommon pattern. 

I will explore this more. 


Code after:
            });
         * ```
         * where `this.environmentInjector` is a provider of `EnvironmentInjector` from @angular/core.
         */
        const environmentInjector = resolverOrInjector ?? this.environmentInjector;
        cmpRef = this.activated = this.location.createComponent(component, {
          index: this.location.length,
          injector,
          environmentInjector,
        } as any);
      }
      // Once the component is created we can push it to our local subject supplied to the proxy
      component$.next(cmpRef.instance);

      // Calling `markForCheck` to make sure we will run the change detection when the
      // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
      enteringView = this.stackCtrl.createView(this.activated, activatedRoute);

      // Store references to the proxy by component
      this.proxyMap.set(cmpRef.instance, activatedRouteProxy);
      this.currentActivatedRoute$.next({ component: cmpRef.instance, activatedRoute });
    }

    this.activatedView = enteringView;

    /**
     * The top outlet is set prior to the entering view's transition completing,
     * so that when we have nested outlets (e.g. ion-tabs inside an ion-router-outlet),
     * the tabs outlet will be assigned as the top outlet when a view inside tabs is
     * activated.
     *
     * In this scenario, activeWith is called for both the tabs and the root router outlet.
     * To avoid a race condition, we assign the top outlet synchronously.
     */
    this.navCtrl.setTopOutlet(this);

    this.stackCtrl.setActive(enteringView).then((data) => {
      this.activateEvents.emit(cmpRef.instance);
      this.stackEvents.emit(data);
    });
  }

  /**
   * Returns `true` if there are pages in the stack to go back.
   */
  canGoBack(deep = 1, stackId?: string): boolean {
    return this.stackCtrl.canGoBack(deep, stackId);
  }

  /**
   * Resolves to `true` if it the outlet was able to sucessfully pop the last N pages.