fix(tabs): preserve route navigation extras when changing tabs (#18493)

fixes #18717
This commit is contained in:
James Manners
2019-12-12 02:46:14 +11:00
committed by Liam DeBeasi
parent b3b3312711
commit 4c8f32fae9
5 changed files with 174 additions and 13 deletions

View File

@ -242,6 +242,22 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
return active ? active.url : undefined;
}
/**
* Returns the RouteView of the active page of each stack.
* @internal
*/
getLastRouteView(stackId?: string): RouteView | undefined {
return this.stackCtrl.getLastUrl(stackId);
}
/**
* Returns the root view in the tab stack.
* @internal
*/
getRootView(stackId?: string): RouteView | undefined {
return this.stackCtrl.getRootUrl(stackId);
}
/**
* Returns the active stack ID. In the context of ion-tabs, it means the active tab.
*/
@ -315,7 +331,7 @@ class OutletInjector implements Injector {
private route: ActivatedRoute,
private childContexts: ChildrenOutletContexts,
private parent: Injector
) {}
) { }
get(token: any, notFoundValue?: any): any {
if (token === ActivatedRoute) {

View File

@ -66,18 +66,53 @@ export class IonTabs {
}
}
/**
* When a tab button is clicked, there are several scenarios:
* 1. If the selected tab is currently active (the tab button has been clicked
* again), then it should go to the root view for that tab.
*
* a. Get the saved root view from the router outlet. If the saved root view
* matches the tabRootUrl, set the route view to this view including the
* navigation extras.
* b. If the saved root view from the router outlet does
* not match, navigate to the tabRootUrl. No navigation extras are
* included.
*
* 2. If the current tab tab is not currently selected, get the last route
* view from the router outlet.
*
* a. If the last route view exists, navigate to that view including any
* navigation extras
* b. If the last route view doesn't exist, then navigate
* to the default tabRootUrl
*/
@HostListener('ionTabButtonClick', ['$event.detail.tab'])
select(tab: string) {
const alreadySelected = this.outlet.getActiveStackId() === tab;
const href = `${this.outlet.tabsPrefix}/${tab}`;
const url = alreadySelected
? href
: this.outlet.getLastUrl(tab) || href;
const tabRootUrl = `${this.outlet.tabsPrefix}/${tab}`;
if (alreadySelected) {
const rootView = this.outlet.getRootView(tab);
const navigationExtras = rootView && tabRootUrl === rootView.url && rootView.savedExtras;
return this.navCtrl.navigateRoot(tabRootUrl, {
...(navigationExtras),
animated: true,
animationDirection: 'back',
});
} else {
const lastRoute = this.outlet.getLastRouteView(tab);
/**
* If there is a lastRoute, goto that, otherwise goto the fallback url of the
* selected tab
*/
const url = lastRoute && lastRoute.url || tabRootUrl;
const navigationExtras = lastRoute && lastRoute.savedExtras;
return this.navCtrl.navigateRoot(url, {
animated: true,
animationDirection: 'back'
});
return this.navCtrl.navigateRoot(url, {
...(navigationExtras),
animated: true,
animationDirection: 'back',
});
}
}
getSelected(): string | undefined {

View File

@ -70,7 +70,7 @@ export class StackController {
if (router.getCurrentNavigation) {
currentNavigation = router.getCurrentNavigation();
// Angular < 7.2.0
// Angular < 7.2.0
} else if (
router.navigations &&
router.navigations.value
@ -191,6 +191,14 @@ export class StackController {
return views.length > 0 ? views[views.length - 1] : undefined;
}
/**
* @internal
*/
getRootUrl(stackId?: string) {
const views = this.getStack(stackId);
return views.length > 0 ? views[0] : undefined;
}
getActiveStackId(): string | undefined {
return this.activeView ? this.activeView.stackId : undefined;
}