F7 Vue: Dynamically adding swipeable tabs?

Goal: Dynamically add a swipeable tab + tab content.

Part that works: Dynamically adding tab links to the NAVBAR.

Part that fails: Dynamically adding tabs (the content).

What I’ve noticed: The dynamically added tabs (content) do NOT have the .swiper-slide classes applied to them, leading me to believe that the “swipeable” part of the tab generation process does not get re-triggered.

What I’ve tried:

  • Adding the class .swiper-slide manually. This half-way works by making the content appear when the non-dynamic slide is slid left/right, but it does not allow the user to go all the way to the new slide. Sort of a ‘peek’, but not usable. Also, clicking on the tab-bar links for the newly-added tabs fails to go to the new tab content.

  • Adding a :key on the <f7-tabs> component that dynamically changes when the slide count changes. In theory this should re-create the entire component. Sadly, this makes the slider even worse: No more sliding at all, no swiper classes. Apparently this does NOT rebuild the swiper part. Perhaps it’s because the tabs all have the .page-content class? I’m not sure, but it feels buggy.

  • Trying to find the swiper object so I can call .update() (see https://swiperjs.com/api/#methods). For some reason there is no .swiper property of the <f7-tabs>. I can select the swiper instance by doing swiper = this.$f7.swiper.get(this.$$('.page-current .swiper-container')), but calling swiper.update() on that does not re-trigger anything. (in fact, that function is “type undefined”, even though I can see it listed in the __proto__ section)

My setup is the same as the sample tabs setup shown for Vue. The only addition being that i use a v-for loop on the tabs, so there will be multiple tab content pages.

Does anyone have a solution for dynamically adding F7 Vue swipeable tabs?

Here’s the part of my template, in case it helps. The Scopes variable is an array.

<f7-tabs swipeable ref="tabs" :key ="'scopes-length-'+Scopes.length">

      <f7-tab
        v-for="scope in Scopes"
        :key ="scope.Scope"
        :id="'tab-'+scope.Scope"
        class="page-content"
      >
        <f7-block>
          <Scope :scope="scope" :minimal="false" style="position:relative;top:-3.5em;"></Scope>
        </f7-block>
      </f7-tab>
</f7-tabs>

Thank you!

And now it works! Apparently I had to both add the right class AND call it on the nextTick, so it’d detect the new DOM element.

Working code within the “add a slide” function:

this.$nextTick()
        .then(() => {
          const swiper = this.$f7.swiper.get(this.$$('.page-current .swiper-container'));
          this.$$('.page-current .swiper-container .page-content.tab').addClass('swiper-slide');
          swiper.updateSlides();
        });
1 Like