Skip to content
Open
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
26 changes: 20 additions & 6 deletions core/src/components/tab-bar/tab-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type { TabBarChangedEventDetail } from './tab-bar-interface';
})
export class TabBar implements ComponentInterface {
private keyboardCtrl: KeyboardController | null = null;
private didLoad = false;

@Element() el!: HTMLElement;

Expand All @@ -40,6 +41,12 @@ export class TabBar implements ComponentInterface {
@Prop() selectedTab?: string;
@Watch('selectedTab')
selectedTabChanged() {
// Skip the initial watcher call that happens during component load
// We handle that in componentDidLoad to ensure children are ready
if (!this.didLoad) {
return;
}

if (this.selectedTab !== undefined) {
this.ionTabBarChanged.emit({
tab: this.selectedTab,
Expand All @@ -65,8 +72,19 @@ export class TabBar implements ComponentInterface {
*/
@Event() ionTabBarLoaded!: EventEmitter<void>;

componentWillLoad() {
this.selectedTabChanged();
componentDidLoad() {
this.ionTabBarLoaded.emit();
// Set the flag to indicate the component has loaded
// This allows the watcher to emit changes from this point forward
this.didLoad = true;

// Emit the initial selected tab after the component is fully loaded
// This ensures all child components (ion-tab-button) are ready
if (this.selectedTab !== undefined) {
this.ionTabBarChanged.emit({
tab: this.selectedTab,
});
}
}

async connectedCallback() {
Expand All @@ -90,10 +108,6 @@ export class TabBar implements ComponentInterface {
}
}

componentDidLoad() {
this.ionTabBarLoaded.emit();
}

render() {
const { color, translucent, keyboardVisible } = this;
const mode = getIonMode(this);
Expand Down
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These screenshots are correct now. They were broken before, but I guess we didn't notice when we approved them. The first tab is selected per the code, so this was committed in the wrong state.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These screenshots are correct now. They were broken before, but I guess we didn't notice when we approved them. The first tab is selected per the code, so this was committed in the wrong state.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 25 additions & 23 deletions core/src/components/tabs/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,32 +65,33 @@ export class Tabs implements NavOutlet {
this.ionNavWillLoad.emit();
}

componentWillRender() {
componentDidLoad() {
this.updateTabBar();
}

componentDidUpdate() {
this.updateTabBar();
}

private updateTabBar() {
const tabBar = this.el.querySelector('ion-tab-bar');
if (tabBar) {
let tab = this.selectedTab ? this.selectedTab.tab : undefined;

// Fallback: if no selectedTab is set but we're using router mode,
// determine the active tab from the current URL. This works around
// timing issues in React Router integration where setRouteId may not
// be called in time for the initial render.
// TODO(FW-6724): Remove this with React Router upgrade
if (!tab && this.useRouter && typeof window !== 'undefined') {
const currentPath = window.location.pathname;
const tabButtons = this.el.querySelectorAll('ion-tab-button');

// Look for a tab button that matches the current path pattern
for (const tabButton of tabButtons) {
const tabId = tabButton.getAttribute('tab');
if (tabId && currentPath.includes(tabId)) {
tab = tabId;
break;
}
}
}
if (!tabBar) {
return;
}

tabBar.selectedTab = tab;
const tab = this.selectedTab ? this.selectedTab.tab : undefined;

// If tabs has no selected tab but tab-bar already has a selected-tab set,
// don't overwrite it. This handles cases where tab-bar is used without ion-tab elements.
if (tab === undefined) {
return;
}

if (tabBar.selectedTab === tab) {
return;
}

tabBar.selectedTab = tab;
}

/**
Expand Down Expand Up @@ -162,6 +163,7 @@ export class Tabs implements NavOutlet {
this.selectedTab = selectedTab;
this.ionTabsWillChange.emit({ tab: selectedTab.tab });
selectedTab.active = true;
this.updateTabBar();
return Promise.resolve();
}

Expand Down
Loading