简体   繁体   中英

show/hide v-tab depend to the related v-checkbox

Hello i'm trying to make a global dynamic component with some extra features. my question is:How can i show/hide v-tab depend on the v-checkbox value? this is my code:

<template>
  <div>
    <v-tabs v-model="activeTab">
      <v-tab v-for="(item, index) in tabs" :key="`${index}-tab`" v-if="checked">
        {{ item.name }}
      </v-tab>

      <v-tab-item v-for="(item, index) in tabs" :key="`${index}-tab`">
        <v-card flat>
          {{ item.name }}
        </v-card>
      </v-tab-item>
      <v-menu
        v-model="menu"
        :close-on-content-click="false"
        :nudge-width="200"
        offset-x
      >
        <template v-slot:activator="{ on, attrs }">
          <div class="d-flex align-center">
            <v-btn icon v-bind="attrs" v-on="on">
              <v-icon>mdi-eye</v-icon>
            </v-btn>
          </div>
        </template>
        <v-card>
          <v-list>
            <v-list-item-group v-model="selectedTabs" multiple>
              <template v-for="(item, index) in tabs">
                <v-list-item :key="`${index}-tab`">
                  <v-list-item-action class="ma-0">
                    <v-checkbox
                      :key="`${index}-tab`"
                      @click="hidecont(item)"
                    ></v-checkbox>
                  </v-list-item-action>
                  <v-list-item-content>
                    <v-list-item-title v-text="item.name"></v-list-item-title>
                  </v-list-item-content>
                </v-list-item>
              </template>
            </v-list-item-group>
          </v-list>
        </v-card>
      </v-menu>
    </v-tabs>
  </div>
</template>

<script>
export default {
  data() {
    return {
      activeTab: 0,
      selectedTabs: [],
      menu: false,
      checked: false,
      tabs: [
        {
          name: "tab1"
        },
        {
          name: "tab2"
        },
        {
          name: "tab3"
        }
      ]
    };
  },

  methods: {
    hidecont(item) {
      console.log("item");
      // i know this will not work in my case
      this.checked = !this.checked;
    }
  }
};
</script>

How it should be: for example when the checkbox(tab1) checked/unchecked => the v-tab(tab1) should be hidden/visible according to the related checkbox... i tried several ways but it doesn't matter in which checkbox i click i got all the v-tabs hidden or visible, the problem hier is i dont know how to pass the right index to the v-tabs component from the check box...

i can not modify the array of Objects because it comes from a rest Api, this is just an example to simplify the issue. it would be great if i can use the item.index or item.name to make it work without modifing the array...

would be so thankfull if some one can help

A few notes:

  1. You don't have to put a v-for on a <template> element surrounding <v-list-item> . If you want multiple v-list-items, put the v-for on <v-list-item> instead.
  2. Don't use v-text when normal text interpolation will do
  3. :key can be given any unique string OR number. If index is unique (and it's guaranteed to be) you don't need to create a string from it, just use "index".
  4. Don't combine a v-if with a v-for . Put the v-if on a wrapper/parent element if you can.

#4 is a tricky one to deal with sometimes, including in your situation here with <v-tab> . You need the v-for to iterate and create multiple tabs, but you can't really put a v-if on a parent element because the parent is <v-tabs> and you don't want that conditionally rendered. You could maybe wrap the v-tab elements in another div or span, but that would intefere with vuetify's CSS, which you could maybe fix, but there is another option.

The other option: create a computed property that will return an array only containing tabs that should be displayed. This new computed property will be what we will loop with v-for to render our tabs and tab-items. Each original tab object in tabs will need a new boolean property that can tell us whether it should be displayed or not. the hidecont() method you have will receive the index of the tab that should be hidden and toggle that boolean property.

Here's the updated code:

<template>
  <div>
    <v-tabs v-model="activeTab">
      <v-tab v-for="(item, index) in computedTabs" :key="index">
        {{ item.name }}
      </v-tab>

      <v-tab-item v-for="(item, index) in computedTabs" :key="index">
        <v-card flat>
          {{ item.name }}
        </v-card>
      </v-tab-item>
      <v-menu
        v-model="menu"
        :close-on-content-click="false"
        :nudge-width="200"
        offset-x
      >
        <template v-slot:activator="{ on, attrs }">
          <div class="d-flex align-center">
            <v-btn icon v-bind="attrs" v-on="on">
              <v-icon>mdi-eye</v-icon>
            </v-btn>
          </div>
        </template>
        <v-card>
          <v-list>
            <v-list-item-group v-model="selectedTabs" multiple>
              <v-list-item v-for="(item, index) in tabs" :key="index">
                <v-list-item-action class="ma-0">
                  <v-checkbox
                    :key="index"
                    @click="hidecont(index)"
                  ></v-checkbox>
                </v-list-item-action>
                <v-list-item-content>
                  <v-list-item-title>{{ item.name }}</v-list-item-title>
                </v-list-item-content>
              </v-list-item>
            </v-list-item-group>
          </v-list>
        </v-card>
      </v-menu>
    </v-tabs>
  </div>
</template>

<script>
export default {
  data() {
    return {
      activeTab: 0,
      selectedTabs: [],
      menu: false,
      checked: false,
      tabs: [
        {
          name: "tab1",
          show: true,
        },
        {
          name: "tab2",
          show: true,
        },
        {
          name: "tab3",
          show: true,
        },
      ],
    };
  },
  computed: {
    computedTabs() {
      return this.tabs.filter((t) => t.show === true);
    },
  },

  methods: {
    hidecont(index) {
      this.tabs[index].show = !this.tabs[index].show;
    },
  },
};
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM