Search code examples
typescriptvue.jstabslazy-loadingbootstrap-vue

BootstrapVue's b-nav with lazy loading


I can't wrap my head around the following problem:

I have a Vue.js component in which I need tabs with routes. I went for a variant of b-nav Tabs style (official docs) and it is working fine, regarding the tabs and routing.
The problem: I can't figure out how to lazy load the tab-content of each item in myItems instead of loading them all on requesting one of the tab routes.

The routes look like this: localhost/items/#tab0, localhost/elements/#tab1 etc.

(Btw: b-tabs have built in lazy loading, but are not routable! Can't use them :-/)

This is the code of my component's template:

<template>
    <div class="tabs">
        <b-nav tabs>
            <b-nav-item
                v-for="(item, index) in myItems"
                :key="item.Id"
                :to="'#tab' + item.Id"
                :active="$route.hash === '#tab' + item.Id || (index === 0 && $route.hash === '')"
            >
                {{ item.name }}
            </b-nav-item>
        </b-nav>

        <div class="tab-content">
            <div
                v-for="(item, index) in myItems"
                :key="item.Id"
                class="tab-pane"
                :class="{ active: $route.hash === '#tab' + item.Id || (index === 0 && $route.hash === '') }"
            >
                <!-- indidivual output here, depending on route | I want to lazy load this -->
            </div>
        </div>
    </div>
</template>

And this my TypeScript code:

<script lang="ts">
    import { Vue, Component, Prop } from "vue-property-decorator";

    @Component()
    export default class MyItemsTabs extends Vue {
        @Prop() readonly myItems!: Item[] | null;
    }
</script>

EDIT: Of, let's say 7 tabs, I need to lazy load only 2, the other's immeditately.

Anybody got an idea? Thanks in advance :-)


Solution

  • I solved it like this:

    I created a component for the tab content:

    Template:

    <div class="tab-content">
      <TabContent
        v-for="(item, index) in myItems"
        class="tab-pane"
        :class="{ active: $route.hash === '#tab' + item.Id || (index === 0 && $route.hash === '') }"
        :key="item.Id"
        :tab-content="item"
      />
    </div>
    

    In the new TabContent component, I check:

    Template:

    <template>
        <div>
            <!-- no "pre-loading" -->
            <TabContent1
                :v-if="$route.hash === "#tab" + item.Id && item.name === 'tabName1'"
            />
    
            <!-- no "pre-loading" -->
            <TabContent2
                :v-if="$route.hash === "#tab" + item.Id && item.name === 'tabName2'"
            />
    
            <!-- loaded immediately -->
            <TabContentDefault v-else />
        </div>
    </template>
    

    This is simplified code, of course. In reality I use functions for the checks and way more properties.