Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(angular): nav controller can pop views after leaving tabs outlet #25690

Merged
merged 15 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion angular/src/directives/navigation/ion-router-outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,19 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
}

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.navCtrl.setTopOutlet(this);
this.activateEvents.emit(cmpRef.instance);
this.stackEvents.emit(data);
});
Expand Down
68 changes: 68 additions & 0 deletions angular/test/base/e2e/src/tabs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,74 @@ describe('Tabs', () => {
});
})

describe('entry url - /tabs/account', () => {
beforeEach(() => {
cy.visit('/tabs/account');
});
it('should pop to previous view when leaving tabs outlet', () => {

cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');

cy.get('#goto-tab1-page2').click();

cy.get('ion-title').should('contain.text', 'Tab 1 - Page 2 (1)');

cy.get('#goto-global').click();

cy.get('ion-title').should('contain.text', 'Global Page');

cy.get('#goto-prev-pop').click();

cy.get('ion-title').should('contain.text', 'Tab 1 - Page 2 (1)');

cy.get('#goto-prev').click();

cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');

/**
* Verifies that when entering the tabs outlet directly,
* the navController.pop() method does not pop the previous view,
* when you are at the root of the tabs outlet.
*/
cy.get('#goto-previous-page').click();
cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');
});
});

describe('entry url - /', () => {
it('should pop to the root outlet from the tabs outlet', () => {
cy.visit('/');

cy.get('ion-title').should('contain.text', 'Test App');

cy.get('ion-item').contains('Tabs test').click();

cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');

cy.get('#goto-tab1-page2').click();

cy.get('ion-title').should('contain.text', 'Tab 1 - Page 2 (1)');

cy.get('#goto-global').click();

cy.get('ion-title').should('contain.text', 'Global Page');

cy.get('#goto-prev-pop').click();

cy.get('ion-title').should('contain.text', 'Tab 1 - Page 2 (1)');

cy.get('#goto-prev').click();

cy.get('ion-title').should('contain.text', 'Tab 1 - Page 1');

cy.get('#goto-previous-page').click();

cy.get('ion-title').should('contain.text', 'Test App');

});
});


describe('entry url - /tabs/account/nested/1', () => {
beforeEach(() => {
cy.visit('/tabs/account/nested/1');
Expand Down
6 changes: 5 additions & 1 deletion angular/test/base/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ const routes: Routes = [
path: 'tabs',
loadChildren: () => import('./tabs/tabs.module').then(m => m.TabsPageModule)
},
{
path: 'tabs-global',
loadChildren: () => import('./tabs-global/tabs-global.module').then(m => m.TabsGlobalModule)
},
{
path: 'nested-outlet',
component: NestedOutletComponent,
Expand All @@ -68,7 +72,7 @@ const routes: Routes = [
component: NestedOutletPage2Component
}
]
}
},
];

@NgModule({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { TabsGlobalComponent } from "./tabs-global.component";

@NgModule({
imports: [
RouterModule.forChild([
{
path: '',
component: TabsGlobalComponent
}
])
],
exports: [RouterModule]
})
export class TabsGlobalRoutingModule { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>

<ion-title>
Global Page
</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<ion-content>
<ion-button id="goto-prev-pop" (click)="navCtrl.pop()">Go To Previous</ion-button>
</ion-content>
</ion-content>
17 changes: 17 additions & 0 deletions angular/test/base/src/app/tabs-global/tabs-global.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Component } from "@angular/core";
import { NavController } from "@ionic/angular";

/**
* This component is used in conjunction with a tabs router-outlet,
* to validate the behavior of different routing APIs (e.g. NavController)
* when leaving and re-entering a router-outlet.
*/
@Component({
selector: 'app-tabs-global',
templateUrl: 'tabs-global.component.html'
})
export class TabsGlobalComponent {

constructor(public navCtrl: NavController) { }

}
13 changes: 13 additions & 0 deletions angular/test/base/src/app/tabs-global/tabs-global.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NgModule } from "@angular/core";
import { IonicModule } from "@ionic/angular";
import { TabsGlobalRoutingModule } from "./tabs-global-routing.module";
import { TabsGlobalComponent } from "./tabs-global.component";

@NgModule({
imports: [
IonicModule,
TabsGlobalRoutingModule
],
declarations: [TabsGlobalComponent]
})
export class TabsGlobalModule { }
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ <h1>Welcome to NESTED PAGE {{id}}</h1>
<p>
<ion-button routerLink="/tabs/account" id="goto-tab1-page1">Go to Tab 1 - Page 1</ion-button>
<ion-button routerLink="/tabs/contact" id="goto-tab2-page1">Go to Tab 2 - Page 1</ion-button>
<ion-button routerLink="/tabs-global" id="goto-global">Go to Global Page</ion-button>
<ion-button routerLink="/tabs-global" id="goto-prev" (click)="navCtrl.pop()">Go to Previous Page (NavController).
</ion-button>
<ion-button routerLink="/tabs/account/nested/{{next()}}" id="goto-next">Go to Next</ion-button>
</p>
</ion-content>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ActivatedRoute } from '@angular/router';
import { Component, OnInit } from '@angular/core';
import { NavController } from '@ionic/angular';

@Component({
selector: 'app-tabs-tab1-nested',
Expand All @@ -9,7 +10,8 @@ export class TabsTab1NestedComponent implements OnInit {
id = '';
constructor(
private route: ActivatedRoute,
) {}
public navCtrl: NavController
) { }

ngOnInit() {
this.id = this.route.snapshot.paramMap.get('id');
Expand All @@ -18,4 +20,5 @@ export class TabsTab1NestedComponent implements OnInit {
next() {
return parseInt(this.id, 10) + 1;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ <h1>Welcome to Tab1</h1>
id="goto-nested-page1-with-query-params">Go to Page 2 with Query Params</ion-button>
<ion-button routerLink="/tabs/lazy/nested" id="goto-tab3-page2">Go to Tab 3 - Page 2</ion-button>
<ion-button routerLink="/nested-outlet/page" id="goto-nested-page1">Go to nested</ion-button>
<ion-button (click)="navCtrl.pop()" id="goto-previous-page">Go to Previous Page</ion-button>
</p>
</ion-content>
3 changes: 3 additions & 0 deletions angular/test/base/src/app/tabs-tab1/tabs-tab1.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component, NgZone } from '@angular/core';
import { NavController } from '@ionic/angular';

@Component({
selector: 'app-tabs-tab1',
Expand All @@ -9,6 +10,8 @@ export class TabsTab1Component {
segment = 'one';
changed = 'false';

constructor(public navCtrl: NavController) {}

ionViewWillEnter() {
NgZone.assertInAngularZone();
setTimeout(() => {
Expand Down