How to load component after a tab is clicked on Vue JS with Bootstrap Vue?

Viewed 10328

I have the following code in HTML (coded with Vue JS & Bootstrap):

<b-tabs card>
        <b-tab title="Followers" :title-link-class="'tab-title-class'">
              Page View graph here
        </b-tab>
        <b-tab title="Orders" :title-link-class="'tab-title-class'">
              Order Numbers graph here
        </b-tab>
        <b-tab title="Sales" :title-link-class="'tab-title-class'">
              <sales-analytics></sales-analytics>
        </b-tab>
        <b-tab title="Profit" :title-link-class="'tab-title-class'">
              Earning graph here
        </b-tab>
</b-tabs>

The card contains 4 tabs, one of which is titled "Sales", and <sales-analytics></sales-analytics> is a component I created to render a graph with Vue-ApexCharts library. However, the graph does not render automatically when the tab is selected. It can only run after I clicked F12 on Chrome, reloading the page does not work either.

I am thinking that the component should only run after the tab has been selected, rather than run altogether when the site is loaded (as this causes render problem when the tab is not selected when the site loads). Does anyone know how to implement this? Or an alternative way to solve this issue?

More stuff from the script section:

<script>
   import Sales from '../analytics/Sales'

export default {
    components: {      
        'sales-analytics': Sales
}
</script>

EDIT: After quite a bit of Googling, I found this: https://github.com/apertureless/vue-chartjs/issues/157 Which has a very similar behaviour to my situation, I want to v-if and mounted to load the component after the tab is selected. Anyone know how to do it?

4 Answers

Thank you all of the comments. And for any future references, I was able to resolve the issue by using v-if to check the current active tab, and then load the component under the scope.

<div v-if=“activeTab === ‘sale’>

As per BootstrapVue docs, it is built in to load components & data only when activating a tab:

Sometimes it's preferred to load components & data only when activating a tab, instead of loading all tabs (and associated data) when rendering the set.

Individual components can be lazy loaded via the lazy prop, which when set doesn't mount the content of the until it is activated (shown), and will be un-mounted when the tab is deactivated (hidden):

<b-tab lazy>

One can also make all tab's lazy by setting the lazy prop on the parent component:

<b-tabs lazy>

Adapted to the code in the question:

<b-tab lazy title="Sales" :title-link-class="'tab-title-class'">
    <sales-analytics></sales-analytics>
</b-tab>

The downside of this solution: the lazy directive cannot be used conditionally. That means, you cannot have some tabs lazy loaded and some not IF you render them using v-for.

component: resolve => {
            require(['./component.vue'], resolve);
        },

This is loaded when it is used. May also need v-if

If you want to force ApexCharts to redraw after tab selection, you should call the refresh() method to redraw chart

<template>
  <div class="example">
    <apexcharts ref="chart" width="500" height="350" :options="chartOptions" :series="series"></apexcharts>
  </div>
</template>

<script>
  afterTabSelection: function() {
    this.$refs.chart.refresh()
  },
</script>
Related