3

I have tabs like this...

<v-tabs v-model="tab" v-on:change="tabbed()" fixed-tabs>
  <v-tab ripple>Tab A</v-tab>
  <v-tab ripple>Tab B</v-tab>
  <v-tab ripple>Tab C</v-tab>
  
  // tab items, etc

I'd like the URL path to determine the tab, and I'd like a tab change to change the path. I wasn't able to do this with path (because I'm new), but I thought I could approximate what I want with a query, like /mypath?tab=2

  data: () => ({
    tab: null
  }),
  methods: {
    tabbed () {
      console.log(`we tabbed, now tab is ${this.tab} and route is ${JSON.stringify(this.$route.path)}`)
      this.$router.replace({ path: this.$route.path, query: { tab: this.tab } })
    }
  },
  created () {
    console.log(`tab is ${this.$route.query.tab}`)
    this.tab = this.$route.query.tab
  }

I thought this would do the trick: on create, get the tab from the query and set the tab model. On tab change, get the tab from the tab model and set the query. But, when I navigate to /mypath?tab=2, or any tab, I end up on the 0th tab and get console output like this:

tab is 2

we tabbed, now the tab is 0 and route is "/mypath"

Something about mounting changes the tab back to zero??

Can I make this work with routes, so I can go to "/mypath/tab-a" Can I at least make this work with queries? It seems like my code is correct, but I don't understand why it fails to work

Community
  • 1
  • 1
goodson
  • 727
  • 2
  • 14
  • 24

2 Answers2

6

Ok, I solved the same by this:

<template>
    <el-tabs v-model="activeTab">
        <el-tab-pane label="tab A" name="tabA"></el-tab-pane>
        <el-tab-pane label="tab B" name="tabB"></el-tab-pane>
        <el-tab-pane label="tab C" name="tabC"></el-tab-pane>
    </el-tabs>
</template>

<script>
    export default {
        data() {
            return {}
        },
        computed: {
            activeTab: {
                set(val) {
                    let query = {...this.$route.query};
                    query.tab = val;
                    this.$router.replace({query: query});
                },
                get() {
                    return (this.$route.query.tab || 'tabA');
                }
            }
        }
    }
</script>

Maybe helpful to you

talkhabi
  • 2,669
  • 3
  • 20
  • 29
  • Thank you for this. I learned about getters and setters from you! But this behaves just like my app. If you add console.log to each getter and setter, then change the tab to (e.g. 1), then navigate with a router push, then press back button on browser, the getter is called, and returns `1`, then (for what reason?) the setter is called and tab is set to `0`. Who's calling the setter?? – goodson Mar 09 '19 at 14:30
  • The `setter` called when the `activeTab` changes. – talkhabi Mar 09 '19 at 16:04
  • Actually this maybe related to difference between `"1"` and `1` (string and integer). it should be better if we check this before assigning: `return this.$route.query.tab*1` in getter or `if (val*1 === this.activeTab*1) return` in setter. – talkhabi Mar 09 '19 at 16:08
  • And I used the `this.$router.replace`, also you can use `this.$router.push`. – talkhabi Mar 09 '19 at 16:10
  • I do appreciate your help. I ended up changing a bunch of component files to make them look like this answer (https://stackoverflow.com/a/54990915/3245272) and it worked. – goodson Mar 09 '19 at 16:14
1

I ran into this problem too and fixed it by using parseInt when handling the route:

this.tab = parseInt(this.$route.query.tab)