Jae
Jae

Reputation: 1157

How to toggle background-color on buttons in VueJS

I am using VueJS, and I have a list of genre buttons that are being dynamically created. These buttons have the ability to be toggled on and off, and when they are toggled on, I want to apply CSS styling (like a blue background) to show they are selected. When they're not selected, I want it to go back to how it is (white background with grey border).

My problem is that I can't achieve the toggling background color feature. I have tried to use variant="primary" as well as other variant options, but it does not work. I have also tried erasing the style="border: 2px solid darkgrey; margin:2px;" while applying variant, however that also doesn't work.

I've resorted to trying to just directly change the CSS of the buttons, using StackOverflow post, but it does not work.

This is the buttons markup in my index.html:

<ul style="list-style: none;">
    <button v-if="ShowALLButton" v-on:click="getAllGenres" class = "btn btn-success" style="left: 0px; margin:2px;">ALL</button>
        <li style="display: inline;">
          <button v-for="buttons in buttonsList" v-if="ShowALLButton" v-on:click="getGenre(buttons)" :pressed.sync="buttons.state" id="buttonID" class = "btn" style="border: 2px solid darkgrey; margin:2px;">
            {{ buttons.genre }}. 
          </button>
        </li>
</ul>

Essentially, the above is a for-loop iterating through my buttonsList, which is a structure that looks like this, containing the genre to display on the buttons, as well as whether it has been toggled on or off (indicated by state, which is initially toggled off, as represented by false). The actual toggling functionality works, because it shows the correct genre(s) results. But for those curious, this is what buttonsList looks like (a list of objects):

[
{ genre: "Folk", state: false },
{ genre: "Rap", state: false },
{ genre: "Pop", state: false },
...
]

The relevant styling from index.html:

<style>
 .am-active {
    background-color: rgb(21, 79, 202);
    color: white;
 }
 .am-not-active {
    background-color: white;
 }
</style>

The function that deals with the buttons toggling and genre selection is in my script.js. It is in the todo! that I need to apply the correct CSS styling to change the buttons, but I am unable to.

// Get Selected Genres
getGenre(button) {
  console.log("ENTERED GET GENRE!!!!!!");
  var selectedGenresItems = []

  // keep track of selected genres
  if (!this.selectedGenres.includes(button)) {
    this.selectedGenres.push(button);
    // todo!
    console.log("inside if");
    button.className += 'am-active';
    console.log(button);
    // ^ the above does not work, it just adds a key with "className" = "undefinedam-active" :(
  }
  else {
    this.selectedGenres.pop(button);
    // todo! must use .am-not-active
  }

  // you can stop reading here if you want
  // print out the list 
  console.log("selectedGenres here:");
  console.log(this.selectedGenres);

  // get only items that have the desired genre
  var num_matches= 0;
  console.log("items length:" + this.items.length);
  console.log("selectedGenres length:" + this.selectedGenres.length);
  for (var start = 0; start < this.items.length; start++) {
    for (var g = 0; g < this.selectedGenres.length; g++) {
      if (this.items[start].primaryGenreName === this.selectedGenres[g].genre) {
        console.log("we found a match!!!");
        num_matches++;
        selectedGenresItems.push(this.items[start]);
      }
    }
  }

  console.log("num_matches: " + num_matches);
  console.log("this is my final list of selectedGenreItems:")
  console.log("object: %O", selectedGenresItems);

  // assign this list to filteredItems (which renders on index.html)
  this.filteredItems = [];
  this.filteredItems = selectedGenresItems;

  // print out the items in this list
  console.log("items in filteredItems:");
  console.log(this.filteredItems);
}

Upvotes: 0

Views: 1121

Answers (1)

Shivam Singh
Shivam Singh

Reputation: 1731

You can bind the class attribute & enable / disable a class on basis of state key of the buttonsList state.

new Vue({
  el: '#app',
  
  data: {
    buttonsList: [
      { genre: "Folk", state: false },
      { genre: "Rap", state: false },
      { genre: "Pop", state: false },
    ]
  },
  
  methods: {
    getGenre (buttons, i) {
      this.buttonsList[i].state = !this.buttonsList[i].state
    }
  }
})
.am-active {
    background-color: rgb(21, 79, 202);
    color: white;
 }
 .am-not-active {
    background-color: white;
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">

  <ul>
    <li>
      <button 
        v-for="(buttons, i) in buttonsList" v-on:click="getGenre(buttons, i)"
        :class="{
          'am-active': buttons.state,
          'am-not-active': !buttons.state
        }"
        :key="i"
      >
        {{ buttons.genre }}. 
      </button>
    </li>
  </ul>

</div>

Upvotes: 1

Related Questions