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(vue): tapping the active tab button now correctly resets the tab stack #24935

Merged
merged 5 commits into from Mar 14, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 27 additions & 4 deletions packages/vue-router/src/locationHistory.ts
Expand Up @@ -92,16 +92,39 @@ export const createLocationHistory = () => {
* and every entry that appears after it.
*/
const clearHistory = (routeInfo?: RouteInfo) => {
Object.keys(tabsHistory).forEach(key => {
tabsHistory[key] = [];
});

if (routeInfo) {

/**
* If there is no route index in locationHistory
* then there will not be any route index in
* tabs either.
*/
const existingRouteIndex = locationHistory.findIndex(r => r.position === routeInfo.position);
if (existingRouteIndex === -1) return;

locationHistory.splice(existingRouteIndex);

/**
* We also need to search the current tab
* to correctly reset the individual tab
* stack. We should not clear the entire
* tab stack as that means we will lose
* a reference to the root tab route.
*/
const { tab } = routeInfo;
const tabHistory = tabsHistory[tab];
if (tab && tabHistory) {
const existingTabRouteIndex = tabHistory.findIndex(r => r.position === routeInfo.position);
if (existingTabRouteIndex === -1) return;

tabsHistory[tab].splice(existingTabRouteIndex);
}

} else {
Object.keys(tabsHistory).forEach(key => {
tabsHistory[key] = [];
});

locationHistory.length = 0;
}
}
Expand Down
19 changes: 14 additions & 5 deletions packages/vue-router/src/router.ts
Expand Up @@ -409,13 +409,22 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
router.push(routerLink);
}

const resetTab = (tab: string, originalHref: string) => {
const resetTab = (tab: string) => {
/**
* Resetting the tab should go back
* to the initial view in the tab stack.
* It should not push a new instance of the
* root tab page onto the stack.
*
* To do this, we get the initial view in the
* tab stack and subtract the position of that
* entry from our current position. From there
* we call router.go() to move us back the
* appropriate number of positions.
*/
const routeInfo = locationHistory.getFirstRouteInfoForTab(tab);
if (routeInfo) {
const newRouteInfo = { ...routeInfo };
newRouteInfo.pathname = originalHref;
incomingRouteParams = { ...newRouteInfo, routerAction: 'pop', routerDirection: 'back' };
router.push({ path: newRouteInfo.pathname, query: parseQuery(newRouteInfo.search) });
router.go(routeInfo.position - currentHistoryPosition);
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/vue/src/components/IonTabButton.ts
Expand Up @@ -47,7 +47,7 @@ export const IonTabButton = /*@__PURE__*/ defineComponent({
*/
if (prevActiveTab === tab) {
if (originalHref !== currentHref) {
ionRouter.resetTab(tab, originalHref);
ionRouter.resetTab(tab);
}
} else {
ionRouter.changeTab(tab, currentHref)
Expand Down
53 changes: 50 additions & 3 deletions packages/vue/test-app/tests/e2e/specs/tabs.js
Expand Up @@ -51,19 +51,66 @@ describe('Tabs', () => {
cy.ionPageHidden('tab1');
});

it('should return to tab root when clicking tab button', () => {
it('should return to tab root when clicking tab button after going back', () => {
cy.visit('http://localhost:8080/tabs')

cy.get('#child-one').click();
cy.ionPageVisible('tab1childone');
cy.ionPageHidden('tab1');

cy.get('#child-two').click();
cy.ionPageHidden('tab1childone');
cy.ionPageVisible('tab1childtwo');

cy.get('ion-tab-button#tab-button-tab1').click();

cy.ionPageVisible('tab1');

// TODO this page is not removed
//cy.ionPageDoesNotExist('tab1childone');
cy.ionPageDoesNotExist('tab1childone');
cy.ionPageDoesNotExist('tab1childtwo');
})

// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24934
it('should return to tab root when clicking tab button', () => {
cy.visit('http://localhost:8080/tabs')

cy.get('#child-one').click();
cy.ionPageVisible('tab1childone');
cy.ionPageHidden('tab1');

cy.get('#child-two').click();
cy.ionPageHidden('tab1childone');
cy.ionPageVisible('tab1childtwo');

cy.ionBackClick('tab1childtwo');
cy.ionPageVisible('tab1childone');
cy.ionPageDoesNotExist('tab1childtwo');

cy.get('ion-tab-button#tab-button-tab1').click();

cy.ionPageVisible('tab1');
cy.ionPageDoesNotExist('tab1chilone');
})

// Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24934
it('should return to tab root after replacing history', () => {
cy.visit('http://localhost:8080/tabs')

cy.get('#child-one').click();
cy.ionPageVisible('tab1childone');
cy.ionPageHidden('tab1');

cy.get('ion-tab-button#tab-button-tab1').click();
cy.ionPageVisible('tab1');
cy.ionPageDoesNotExist('tab1chilone');

cy.get('#child-one').click();
cy.ionPageVisible('tab1childone');
cy.ionPageHidden('tab1');

cy.get('ion-tab-button#tab-button-tab1').click();
cy.ionPageVisible('tab1');
cy.ionPageDoesNotExist('tab1chilone');
})

it('should be able to create and destroy tabs', () => {
Expand Down