1

I'm trying to create a list where every list item contains a button and i want a user to be able to click multiple button. I'm generating my list like so:

    <ul>
      <li v-for="item in items" :key="item.id">
        <button type="button">{{item.title}}</button>
      </li>
    </ul>

but the problem with my code is whenever a user click a button, it turns the rest of the buttons to "unclicked". been trying to play with the focus and active stats but even with just css i cant get to enable multiple select . i did manage to change the look of the current selected button:

button:focus {
  outline: none;
  background-color: #6acddf;
  color: #fff;
}

any idea how can i allow multiple buttons to be clicked?

to make things a bit clearer, i am going to create an AJAX call later and pass the item.id of each item where it's button is clicked

2
  • 2
    Add another object to the item, like isClicked where is false by default. An then on your click method, like clicked, set the value to true and append some class with some styles. Commented Jan 2, 2019 at 15:45
  • was hoping not to get this answer. i would much rather avoid changing the data structure if possible Commented Jan 2, 2019 at 15:53

2 Answers 2

3

I would much rather avoid changing the data structure if possible

Well you have to store somewhere that you clicked on the clicked item.

If you can't edit the items array then you can always create a new one, like isClicked where you store those values.

new Vue({
  el: '#app',
  data: {
    items: [{
        id: 1,
        title: 'foo'
      },
      {
        id: 2,
        title: 'bar'
      },
      {
        id: 3,
        title: 'baz'
      }
    ],
    isClicked: []
  },
  beforeMount() {
    // set all values to false
    this.items.forEach((item, index) => this.$set(this.isClicked, index, false))
  },
  methods: {
    clicked(index) {
      // toggle the active class
      this.$set(this.isClicked, index, !this.isClicked[index])
    }
  }
})
.active {
  background: red
}
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <div v-for="(item, index) in items" :key="index">
    <button @click="clicked(index)" :class="{'active': isClicked[index]}">{{item.title}}</button>
  </div>
</div>

Or you can use vuex for storing those values.


However you can just use Vues event to manipulate the classList property, like:

new Vue({
  el: '#app',
  data: {
    items: [1, 2, 3, 4, 5, 6, 7]
  }
})
.active {
  color: red
}
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <button v-for="i in items" @click="e => e.target.classList.toggle('active')">{{ i }}</button>
</div>

But it doesn't feel right, IMHO.

Also you can use cookies or localStorage to store those states. So it's really up to you.

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

Comments

0

Use id attribute for list items to make it unique.

<ul>
    <li v-for="item in items" :key="item.id" :id="item.id">
        <button type="button" @click="doThis">{{item.title}}</button>
    </li>
</ul>


new Vue({
  el: '#app',
  data: {},
  methods: {
      doThis() { 
          // Use this to access current object
      }
  }
});

Comments

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.