bootstrap-vue tabs - open a tab content given an anchor in the url

Viewed 5019

I'm using bootstrap-vue for a SPA and I am working on a page where we need to nest some content within b-tabs.

By given a url with an anchor (eg: www.mydomain.com/page123#tab-3) I would like to show the content under Tab 3.

Question: How do I do it within bootstrap-vue? Is there a native function I can use for that? reference: (I couldn't find it in the docs: https://bootstrap-vue.js.org/docs/components/tabs/)


Here is my code:

<b-tabs>


  <b-tab title="Tab 1" active>
    Tab 1 content
  </b-tab>

  <b-tab title="Tab 2">
    Tab 2 content
  </b-tab>

  <b-tab title="Tab 3">
    Tab 3 content
  </b-tab>


</b-tabs>

And this is the rendered html code:

<div class="tabs">
  <div class="">
    <ul role="tablist" tabindex="0" class="nav nav-tabs">
      <li class="nav-item">
        <a role="tab" tabindex="-1" href="#" class="nav-link active">Tab 1</a>
      </li>
      <li class="nav-item">
        <a role="tab" tabindex="-1" href="#" class="nav-link">Tab 2</a>
      </li>
      <li class="nav-item">
        <a role="tab" tabindex="-1" href="#" class="nav-link">Tab 3</a>
      </li>
    </ul>
  </div>
  <div class="tab-content">
    <div class="tab-pane show fade active">
      Tab 1 content
    </div>
    <div class="tab-pane fade" style="display: none;">
      Tab 2 content
    </div>
    <div class="tab-pane fade" style="display: none;">
      Tab 3 content
    </div>
  </div>
</div>
2 Answers

b-tabs is supposed to be used for local (non-url) based content (the href prop on b-tab is deprecated)

You can, however, easily use b-nav and divs to generate URL navigation based tabs:

<div class="tabs">
  <b-nav tabs>
    <b-nav-item to="#" :active="$route.hash === '#' || $route.hash === ''">
      One
    </b-nav-item>
    <b-nav-item to="#two" :active="$route.hash === '#two'">
      Two
    </b-nav-item>
    <b-nav-item to="#three" :active="$route.hash === '#three'">
      Three
    </b-nav-item>
  </b-nav>
  <div class="tab-content">
    <div :class="['tab-pane', { 'active': $route.hash === '#' || $route.hash === '' }]" class="p-2">
      <p>Tab One (default) with no hash</p>
    </div>
    <div :class="['tab-pane', { 'active': $route.hash === '#two' }]" class="p-2">
      <p>Tab One with hash #two</p>
    </div>
    <div :class="['tab-pane', { 'active': $route.hash === '#three' }]" class="p-2">
      <p>Tab One with hash #three</p>
    </div>
  </div>
</div>

This assumes you are using Vue router.

For anyone looking to solve this problem here is my workaround:

<template>
  <b-card no-body>
    <b-tabs card :value="activeTabIndex" @input="changeRoute">
      <b-tab title="A" no-body>
        <p>Content A</p>
      </b-tab>
      <b-tab title="B" no-body>
        <p>Content B</p>
      </b-tab>
      <b-tab title="C" no-body>
        <p>Content C</p>
      </b-tab>
    </b-tabs>
  </b-card>
</template>

<script>
export default {
  data: () => {
    return {
      tabsPathsDictionary: ['/[yourPathToTabs]/a', '/[yourPathToTabs]/b', '/[yourPathToTabs]/c']
    }
  },
  computed: {
    activeTabIndex () {
      const route = this.$route.path.toLowerCase();
      const index = this.tabsPathsDictionary.findIndex(element => element === route) || 0; 
      return index;
    }
  },
  methods: {
    changeRoute (value) {
      this.$router.push(this.tabsPathsDictionary[value])
    }
  }
}
</script>

The usual active property on the default tab can not be used with this solution, as it will always redirect to that tab on reload. Of course the solution can be used with url params by using this.$route.params accordingly instead of this.$route.path (which would require some refactoring). The example assumes using Vue Router.

Related