1

I'm new to Vue.js and I guess I'm missing some point on the way it works. I'm trying to build the following:

  1. Fetch a list of plans from a REST API - done
  2. Display the plans as buttons with v-for - done
  3. Allow the user to click in one of those buttons / plans to mark it as chosen

My code to print the buttons inside bootstrap columns:

<b-col lg="4" class="plan" v-for="plan in plans" :key="plan.id">
<b-button block variant="secondary" v-on:click="pickPlan(plan.id)">
    <p class="price">€ {{plan.price}}</p>
    <p class="plan">{{plan.name}}</p>
</b-button>

My problem: how can I make it so if the user clicks on some button it changes the property variant="primary" in that button and sets all others to variant="secondary"?

Thank you.

maxpaj
  • 4,239
  • 3
  • 21
  • 42
TCB13
  • 2,826
  • 2
  • 34
  • 62

2 Answers2

2

You can bind the variant attribute to any data available on your Vue component or use it together with inline JavaScript, like this:

<b-col lg="4" class="plan" v-for="plan in plans" :key="plan.id">
    <b-button block :variant="plan.id === chosenPlan.id ? 'primary' : 'secondary'" v-on:click="pickPlan(plan.id)">
        <p class="price">€ {{plan.price}}</p>
        <p class="plan">{{plan.name}}</p>
    </b-button>
</b-col>

And then make sure to set chosenPlan in your pickPlan(planId) method.

maxpaj
  • 4,239
  • 3
  • 21
  • 42
  • Many thanks you solution is easy to implement and doesn't envolve chafing the `plans` array. I ended up creating a method to hide the `if` logic from the template code as described in here https://stackoverflow.com/questions/40522634/can-i-pass-parameters-in-computed-properties-in-vue-js – TCB13 Dec 11 '17 at 01:58
  • So my final template code was `` and the script `methods: { planButtonVariant: function (plan) { return plan.id === this.chosenPlan.id ? "primary" : "outline-secondary" },` – TCB13 Dec 11 '17 at 01:59
1

One way to solve it is to extend plan object and add to it extra called variant or picked and use this property to bind to variant attribute in template

<template>
  <div>
    <b-col lg="4" class="plan" v-for="plan in plans" :key="plan.id">
      <b-button block v-bind:variant="picked ? 'primary' : 'secondary'" v-on:click="pickPlan(id)">
          <p class="price">€ {{plan.price}}</p>
          <p class="plan">{{plan.name}}</p>
      </b-button>
    </b-col>
  </div>
</template>

<script>
export default {
  data() {
    return {
      plans: [
        { id: 1, name: 'Plan name 1', price: 12.00, picked: false },
        { id: 2, name: 'Plan name 2', price: 24.00, picked: true },
      ]
    }
  },
  methods: {
    pickPlan(id) {
      this.plans = this.plans.map(p => {
        if(p.id === id) {
          return { ...p, picked: true }
        }
        return { ...p, picked: false }
      })
    }
  }
}
</script>
Piotr Pasieka
  • 1,553
  • 9
  • 14