ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
50.93k stars 13.51k forks source link

bug: vue, cannot wrap tab button in custom component #25919

Open DoloreMentale opened 2 years ago

DoloreMentale commented 2 years ago

Prerequisites

Ionic Framework Version

Current Behavior

All ion-tab-buttons in my case are rendered using v-for. tabState.activeTab and tabState.tabs are empty.

Found similar issue, seems it has been fixed in previos version, but problem still appears: https://github.com/ionic-team/ionic-framework/issues/22847

image

ion-tab-button click causes an error:

image

Expected Behavior

ion-tab-button click should push to another route

Steps to Reproduce

Just use v-for on ion-tab-button

ion-tabs:

<template>
    <ion-tabs>
      <ion-router-outlet />

      <ion-tab-bar ref="tabBar" slot="bottom" :translucent="true">
        <tab-entity v-for="(tab, index) in tabs" :key="index" :tab="tab" />
      </ion-tab-bar>
    </ion-tabs>
</template>

<script>
import { IonTabBar, IonTabs, IonRouterOutlet } from '@ionic/vue';
import TabEntity from '@/components/tabs/tab.entity';

export default {
  name: 'TabsEntity',
  components: { IonTabBar, IonTabs, IonRouterOutlet, TabEntity },
  props: {
    tabs: {
      type: Array,
      default: () => []
    }
  },
}
</script>

ion-tab-button:

<template>
  <ion-tab-button :tab="tab.name" :href="tab.href">
    <ion-icon :icon="tab.icon" />
    <ion-label v-if="tab.value">{{ tab.value }}</ion-label>
  </ion-tab-button>
</template>

<script>
import { IonTabButton, IonIcon, IonLabel } from '@ionic/vue'

export default {
  name: 'TabEntity',
  components: { IonTabButton, IonIcon, IonLabel },
  props: {
    tab: {
      type: Object,
      default: () => {}
    },
  },
}
</script>

Code Reproduction URL

https://github.com/DoloreMentale/ion-tabs-bug-reproduction

Ionic Info

Ionic:

Ionic CLI : 6.19.0 (C:\nvm\v16.14.0\node_modules\@ionic\cli) Ionic Framework : @ionic/vue 6.2.6

Capacitor:

Capacitor CLI : 4.2.0 @capacitor/android : not installed @capacitor/core : 4.2.0 @capacitor/ios : not installed

Utility:

cordova-res : not installed globally native-run : 1.7.0

System:

NodeJS : v16.14.0 (C:\Program Files\nodejs\node.exe) npm : 8.7.0 OS : Windows 10

Additional Information

No response

ionitron-bot[bot] commented 2 years ago

Thanks for the issue! This issue has been labeled as needs reproduction. This label is added to issues that need a code reproduction.

Please reproduce this issue in an Ionic starter application and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.

If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.

For a guide on how to create a good reproduction, see our Contributing Guide.

DoloreMentale commented 2 years ago

Reproduction can be found here: https://github.com/DoloreMentale/ion-tabs-bug-reproduction

Besides that, the problem seems to be quite usual. I discovered that the issue is with wrapper component for ion-tab-button. Although the component is rendered without any additional tags, something that gets buttons inside ion-tab-bar cannot do that.

Steps for recreation are the same:

  1. yarn / npm install
  2. yarn / npm run serve
  3. Click on any ion-tab-button and check the console for error logs
liamdebeasi commented 2 years ago

Thanks. The problem here is that we expect the IonTabBar to pass _getTabState to child IonTabButton elements: https://github.com/ionic-team/ionic-framework/blob/9b244dd3f01e2a79f4374b5de5304ba4f2035ddd/packages/vue/src/components/IonTabBar.ts#L61-L74

Since IonTabButton is wrapped in a custom Vue component and not a direct child, this function is not passed down. As a result, the click handler throws an error because it is missing required data. As a temporary workaround, you can update your app to ensure that IonTabButton is always a direct child of IonTabBar.

DoloreMentale commented 2 years ago

@liamdebeasi thanks for your reply!

g5becks commented 9 months ago

Thanks. The problem here is that we expect the IonTabBar to pass _getTabState to child IonTabButton elements:

https://github.com/ionic-team/ionic-framework/blob/9b244dd3f01e2a79f4374b5de5304ba4f2035ddd/packages/vue/src/components/IonTabBar.ts#L61-L74

Since IonTabButton is wrapped in a custom Vue component and not a direct child, this function is not passed down. As a result, the click handler throws an error because it is missing required data. As a temporary workaround, you can update your app to ensure that IonTabButton is always a direct child of IonTabBar.

It would be really nice if this were stated in the docs. Spent a half an hour trying to figure out why I was getting this error.