Reputation: 25
I am writing an app in Vue.js and cannot find a solution to my problem.
Here's my codeSandbox
I have an array of objects, that I transform into an object with false values for each key.
sizesArray: [
{ number: "30", id: 1 },
{ number: "36", id: 2 },
{ number: "40", id: 3 }
],
sizesObject: {
"30": false,
"36": false,
"40": false
},
I can target each value individually, but how can I toggle the buttons so that only one value is true at a time, instead of being toggled individually as I have now?
It seems that For-in loop or a watcher would be great for that, I'm just not sure how to approach it.
I've been sitting on this problem for a couple of hours, and cannot seem to find something similar on stack overflow. Thank you!
Upvotes: 0
Views: 1262
Reputation: 219
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>
Upvotes: 1
Reputation: 9118
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>
Upvotes: 1
Reputation: 3907
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
Upvotes: 2