6
votes

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
The simplest solution I can think of is using a Route Query like www.mydomain.com/page123#?3 and then you simply check the Query on the Mounted and set the tab with that number to active.Badgy
That's an interesting approach, and the most common solution I was able to find on the internet would be to write some custom function. I was wondering if there is a built-in feature in boootstrap, or bootstrap-vue, or vue itself.Adriano

2 Answers

11
votes

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.

0
votes

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.