1

I'm trying to toggle classes for multiple elements in Vuejs 2.0, I have the following set of buttons which has a class of btn-primary. Clicking a button shows a sub-group of that particular element. This is my code:

<button class="btn btn-primary btn-xs" v-on:click.prevent="getTags('investor')">Investor</button>
<button class="btn btn-primary btn-xs" v-on:click.prevent="getTags('research')">Research</button>
<button class="btn btn-primary btn-xs" v-on:click.prevent="getTags('company')">Company</button>

This shows the following element:

<div v-if="tag.investor">
    <button class="btn btn-primary btn-xs" v-on:click.prevent="selectTags('Investor - Mutual Funds')">Mutual Fund</button>
    <button class="btn btn-primary btn-xs" v-on:click.prevent="selectTags('Investor - Insurance')">Insurance</button>
    <button class="btn btn-primary btn-xs" v-on:click.prevent="selectTags('Investor - FII')">FII</button>
</div>
<div v-if="tag.research">
    <button class="btn btn-primary btn-xs" v-on:click.prevent="selectTags('Research - Tier I')">Research - Tier I</button>
    <button class="btn btn-primary btn-xs" v-on:click.prevent="selectTags('Research - Tier II')">Research - Tier II</button>
</div>

I have the following in data():

tag: {
    investor: false,
    research: false,
    company: false,
    others: false,
 },

And in methods:

getTags: function (tag) {
    this.tag.investor = this.tag.research = this.tag.company = this.tag.others = false
    if(tag == 'investor')
    {
        this.tag.investor = true
    }
    if(tag == 'research')
    {
        this.tag.research = true
    }
    if(tag == 'company')
    {
        this.tag.company = true
    }
    if(tag == 'others')
    {
        this.tag.others = true
    }
},

I want to have a class of btn-warning and remove btn-primary once any child element is being selected. Any ideas how to implement this, I don't want to have individual data elements and toggle class.

2 Answers 2

9

I'd like to suggest a data driven approach for your Vue. Consider this data structure:

const tags = {
   Investor:[
     {display:"Mutual Fund", value:"Investor - Mutual Funds"},
     {display:"Insurance", value:"Investor - Insurance"},
     {display:"FII", value:"Investor - FII"},
   ],
   Research:[
     {display:"Research - Tier I", value:"Research - Tier I"},
     {display:"Research - Tier II", value:"Research - Tier II"},
  ]
}

If you use that, then you can clean up your template considerably and handle any additional tags that you add to your data structure.

<div id="app">
  <button v-for="(obj, key) in tags"
          :key="key"
          @click="currentTag = key"
          class="btn btn-xs btn-primary">
    {{key}}
  </button>

  <div>  
    <button v-for="tag in tags[currentTag]"
            :key="tag"
            class="btn btn-xs"
            :class="tagClass(tag)"
            @click="selectTags(tag.value)">
      {{tag.display}}
    </button>
  </div>
</div>

Your Vue also looks a lot cleaner.

new Vue({
  el:"#app",
  data:{
    currentTag: null,
    tags,
    selectedTags:[]
  },
  methods:{
    selectTags(tag){
      const index = this.selectedTags.findIndex(t => t == tag)

      if (index >= 0)
        this.selectedTags.splice(index, 1)
      else
        this.selectedTags.push(tag)
    },
    tagClass(tag){
      const isSelected = this.selectedTags.includes(tag.value)

      return {
        'btn-warning': isSelected,
        'btn-primary': !isSelected
      }
    }
  }
})

Here is an example.

Sign up to request clarification or add additional context in comments.

6 Comments

Hi thanks for the answer, it work perfect. One final doubt, what if I want to select only one end element. Just for knowledge.
@NitishKumar When you say "one end element" what do you mean? Do you mean select one tag? One tag per category?
Only one tag from any category. I mean I want the final or selectedTag to be one value not array of multiple value.
@NitishKumar Something like this.
Yes, that's perfect. Thanks for the update and helping me out. Cheers
|
3

You can use the v-bind:class directive.

<button 
  class="btn btn-xs" 
  v-bind:class="{ 'btn-warning': tag.research, 'btn-primary': !tag.research }"
  v-on:click.prevent="selectTags('Research - Tier I')"
>
  Research - Tier I
</button>

1 Comment

i know I an use v-bind:class but I'm having lot more elements which will be repetitive and very difficult to manage as all element class will be toggled then. Like suppose what will be the happen to Research Tier II element, or what if I've Research Tier III, IV element

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.