[Vuejs]-Only one button active at a time depending on state

1đź‘Ť

âś…

Arguably a better approach than the loop method is to just store a reference to the currently active item and reset it on new selection. See CodeSandbox Example.

toggle: function(number) {
  if (this.activeIndex !== null && this.activeIndex !== number)
    this.sizesObject[this.activeIndex] = false;
  this.sizesObject[number] = !this.sizesObject[number];
  this.activeIndex = number;
}

And call it:

<button
      v-for="size in this.sizesArray"
      @click="toggle(size.number)"
      :class="{active: sizesObject[size.number]}"
      :key="size.key"
    >{{size.number}}</button>
👤Beyers

2đź‘Ť

You can simply loop through all entries on any click and set them to false. After that you could set the correct one to true. That’s just a pretty rudimentary solution and could be improved. However, it visualizes the way to go.

  for (const o in this.sizesObject) {
    this.sizesObject[o] = false;
  }

  this.sizesObject[sizeNumber] = true;

https://codesandbox.io/s/wispy-bird-chk35

👤Aer0

1đź‘Ť

You don’t need sizesObject in order to implement that logic.
Instead, you can add a data “selected” which stores the selected/clicked button’s “id”.
And you can choose the active class by checking whether the “selected” value is equal to “id” or not.

This is the full code,

<template>
  <div class="hello">
    <button
      v-for="size in this.sizesArray"
      @click="setSelected(size.id)"
      :class="{active: selected === size.id}"
      :key="size.key"
    >{{size.number}}</button>
    <br>
    <br>
    {{sizesObject}}
    {{selected}}
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      sizesArray: [
        { number: "30", id: 1 },
        { number: "36", id: 2 },
        { number: "40", id: 3 }
      ],
      selected: null
    };
  },
  methods: {
    setSelected: function(value) {
      this.selected = value;
    }
  },
  props: {
    msg: String
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.active {
  background-color: rebeccapurple;
  color: white;
}
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

Leave a comment