svelte-ionic-app
svelte-ionic-app copied to clipboard
Tabs and Subpages
I'm trying to achieve a navigation stack with tabs and subpages but it seems like this is not possible at the current state. I took the tabs-demo and extended it with a subpage which is shown correctly but when navigating back the tab content stays blank because the ion-tab HTML element has still the tab-hidden class attached.
So I decided to update ionic-svelte to the latest version but that made it even worse. With 0.5.82 I can't even navigate to a subpage. A button wich links to a subpage simply does nothing.
Is it me doing something wrong or is this simply not possible atm?
Hi there - I see indeed the class tab-hidden is added to the innertab. There is something in Tab.tsx that does that based on which tab is made active. And looking into Tab.tsx I see the activation is done by selecting the tab.
You can see this behaviour by invoking the blank page per your route change and then click the tab that should be shown.
So (in theory - I haven't tried this) - the button that says "go back" should bring the browser back to the /tab/test1 route and trigger the select method on the tabs, so ensure the tab is selected and shown again
Hope this helps
Here's my workaround. In my pages:
import { pushPathStack, popPathStack } from '$services/navigation.service'
const ionViewWillEnter = async () => {
pushPathStack();
}
<ion-buttons slot="start">
<ion-button
on:click={() => {
goto(popPathStack());
}}>
<ion-icon slot="icon-only" icon={allIonicIcons.arrowBackOutline} />
</ion-button>
</ion-buttons>
navigation.service.ts
:
export let pathStack: string[] = []
import { afterNavigate } from '$app/navigation';
import { base } from '$app/paths'
export const pushPathStack = async () => {
afterNavigate(({from}) => {
if (from !== null && from?.url !== null) {
pathStack.push(from?.url.pathname || base || '/');
} else {
pathStack.push(base || '/');
}
});
}
export const popPathStack = () => {
const path = pathStack.pop();
return path || base || '/';
}
Thanks @Tommertom for pointing me into the right direction. I had a look into the IonTabs implementation and noticed that the goto (Line 32) was always pointing to the tab itself and not to the given path. Therefore navigating to subroutes of a tab was indeed not possible. I made my own implementation and changed it to navigate to the given path and selecting the related tab aftwerwards. Here is my Code:
<script lang="ts">
// @ts-nocheck
import { onMount } from 'svelte'
import { page, navigating } from '$app/stores'
import { goto } from '$app/navigation'
export let ionTabsDidChange = () => {}
export let ionTabsWillChange = () => {}
export let slot = 'bottom'
/**
An array of tab objects containing label, icon, and tab properties.
@type {{label: string; icon: string; tab: string;}[]}
*/
export let tabs = []
let ionTabBarElement
let controller
// we need relative path for the goto to function properly and to allow for relative tab definitions
const { pathname } = $page.url
const pathSplit = pathname.split('/')
let currentTabName = pathSplit[pathSplit.length - 1] // we don't want to use at(-1) because of old browsers
const relativePath = pathname.replace(currentTabName, '')
// we need to capture the router changes - to support a-href navigation and other stuff
$: if ($navigating && $navigating.to) {
tabs.forEach(async (tab) => {
console.log(tab.tab)
if ($navigating.to.url.pathname.includes(relativePath + tab.tab)) {
currentTabName = tab.tab
await goto($navigating.to.url.pathname)
controller.select(tab.tab)
}
})
}
onMount(async () => {
// reassignment needed after onMount
controller = ionTabBarElement
controller.select(currentTabName)
})
const tabBarClick = async (selectedTab) => {
currentTabName = selectedTab
await goto(relativePath + selectedTab)
controller.select(selectedTab)
}
</script>
<ion-tabs
on:ionTabsDidChange={ionTabsDidChange}
on:ionTabsWillChange={ionTabsWillChange}
bind:this={ionTabBarElement}
>
<slot />
{#if slot === 'bottom' || slot === ''}
<ion-tab-bar slot="bottom">
{#each tabs as tab}
<ion-tab-button
tab={tab.tab}
on:keydown={() => {
tabBarClick(tab.tab)
}}
on:click={() => {
tabBarClick(tab.tab)
}}
>
<ion-label>{tab.label}</ion-label>
<ion-icon icon={tab.icon} />
</ion-tab-button>
{/each}
</ion-tab-bar>
{/if}
{#if slot === 'top'}
<ion-tab-bar slot="top">
{#each tabs as tab}
<ion-tab-button
tab={tab.tab}
on:keydown={() => {
tabBarClick(tab.tab)
}}
on:click={() => {
tabBarClick(tab.tab)
}}
>
<ion-label>{tab.label}</ion-label>
<ion-icon icon={tab.icon} />
</ion-tab-button>
{/each}
</ion-tab-bar>
{/if}
</ion-tabs>
I dont observed any side-effects by now and navigating throug the history also seem to work fine.
Thank you both. :)
@RingoRohe - thx for the code contribution. I added it in IonTabs.svelte
And meanwhile I am also looking to rebuild ionic-svelte in order to resolve some of the issues with overlays and navigation.
This also means possible ditching IonTabs.svelte - see https://github.com/Tommertom/svelte-ionic-app/issues/91
What are you thoughts on this?
Happy hearing your views on a rebuild- https://github.com/Tommertom/svelte-ionic-app/issues/93
Same @burggraf ! Is your code snippet for Tabs or more for Nav? I rather rely on the router for IonTabs.
Thx