Jer
Jer

Reputation: 231

Vuejs - how to awoid to put numbers in v-if

I have got a left menu, that can show contents depending of the id of the selected menu.

But i got === 0 and === 1 in the v-if and I would like to avoid to put numbers manually there.

<template>
  <v-card elevation="2" class="experiences-container">
    <v-layout row wrap>
      <v-flex md3 sm12 xs12 class="relative">
        <div class="settings-list"
          :class="switchSetting ? 'open' : ''">
          <v-list>
            <v-list-tile
              v-for="(item, index) in menu"
              :key="index"
              :class="['experience-item', index === idSelectedSetting ? 'active' : '']"
              @click="updateSelectedSetting(index)"
            >
              <v-list-tile-content>
                <v-list-tile-title>{{ item.name }}</v-list-tile-title>
              </v-list-tile-content>
              <v-list-tile-action v-if="index == idSelectedSetting ? true : false">
                <v-icon>chevron_right</v-icon>
              </v-list-tile-action>
            </v-list-tile>
          </v-list>
        </div>

      </v-flex>
      <v-flex md9 sm12 xs12>
          <UserPasswordEdition class="setting-details"
            v-if="idSelectedSetting === 0"
            :class="switchSetting ? 'close' : ''"
          />
          <div
            class="setting-details"
            :class="switchSetting ? 'close' : ''"
            v-if="idSelectedSetting === 1">
            <div class="WIP">Autre menu</div>
          </div>
      </v-flex>
    </v-layout>
  </v-card>
</template>

--

data() {
    return {
        menu: [
            { name: 'Mot de passe' },
            { name: 'Autre menu' }
        ],
      idSelectedSetting: 0,
      switchSetting: false,
    };
  },
  methods: {
    updateSelectedSetting(id) {
      this.idSelectedSetting = id;
      this.closeSwitchSetting();
    },
    openSwitchSetting() {
      this.switchSetting = true;
    },
    closeSwitchSetting() {
      this.switchSetting = false;
    }
  }

--

I just wanna change the v-if here:

<UserPasswordEdition class="setting-details"
            v-if="idSelectedSetting === 0"
            :class="switchSetting ? 'close' : ''"
          />
          <div
            class="setting-details"
            :class="switchSetting ? 'close' : ''"
            v-if="idSelectedSetting === 1">
            <div class="WIP">Autre menu</div>
          </div>

I tried a v-for but I couldn't make it, or I don't know how to use it in this situation because it shows both content on each menu and I don't want that.

Thanks!

Upvotes: 0

Views: 1207

Answers (2)

Radu Diță
Radu Diță

Reputation: 14171

You can create an array with all your options. You'll probably need to use :is to render individual components.

You should also add an index on your data and compare it with a selectedIndex when rendering.

data() {
 return {
  selectedIndex: 0, //default value goes here
  itemsToShow: [
   {
    id: 0,
    component: 'UserPasswordEdition',
   },
   {
    id: 1,
    component: 'OtherComponent'
   }
  ]
 }
}

And then update your template

<template>
  ...
  <v-flex md9 sm12 xs12>
    <component v-for="option in itemsToShow" 
               :key="option.id" 
               :is="option['component']
               v-if="selectedIndex === option.id"
    />
  </v-flex>
</template>

Note: this works if you need to pass the same props to all components, otherwise your rendering logic will grow a little more complex.

Edit: added this after @Jer got a warning about not using v-for and v-if on the same directive.

You can also use a computed property to filter your array

computed: {
 filteredItemsToShow() {
   return this.itemsToShow.filter(item => item.id === this.selectedIndex)
  }
}

And then use filteredItemsToShow when rendering

<template>
  ...
  <v-flex md9 sm12 xs12>
    <component v-for="option in filteredItemsToShow" 
               :key="option.id" 
               :is="option['component']
    />
  </v-flex>
</template>

Notice the removal of v-if as it is baked into the computed property.

Upvotes: 1

Mikhail Sidorov
Mikhail Sidorov

Reputation: 1434

You can extract your condition to computed property. Example:

<template>
  ...
  <v-flex md9 sm12 xs12>
    <UserPasswordEdition class="setting-details"
      v-if="!isSelectedSetting"
      :class="switchSetting ? 'close' : ''"
    />
    <div
      class="setting-details"
      :class="switchSetting ? 'close' : ''"
      v-if="isSelectedSetting"
    >
      <div class="WIP">Autre menu</div>
    </div>
  </v-flex>
</template>

<script>
  export default {
    data() {
      return {
        menu: [
          { name: 'Mot de passe' },
          { name: 'Autre menu' }
        ],
        idSelectedSetting: 0,
        switchSetting: false,
      };
    },
    computed: {
      isSelectedSetting() {
        return this.idSelectedSetting === 1
      }
    }
  }
</script>

Upvotes: 0

Related Questions