0

So i am making a small list in which i have a list of car companies and an option for users to select their favorite one. I have an array of objects which returns the name and a certain property named starred. I have a method setStarred which sets the starred of selected to true. But what i am trying to achieve is to have the option to only select one at a time, so if i select BMW, the starred for other two should be toggled to false. Right now i can toggle all of them at the same time.

Please check this working codepen.

Check out the working example below:-

new Vue({
  el: '#app',
  data() {
    return {
      cars: [{
          name: 'Toyota',
          starred: false
        },
        {
          name: 'BMW',
          starred: false
        },
        {
          name: 'Ford',
          starred: false
        }
      ]
    }
  },
  methods: {
    setStarred(item) {
      item.starred = !item.starred
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<link rel="stylesheet"  href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'>

<div id="app">
  <v-app id="inspire">
    <v-container>
      <v-layout justify-center column>
        <v-flex xs6 v-for="(car,index) in cars" :key="index">
          <h2>{{car.name}}
            <v-icon :color="car.starred ? 'primary': '' " @click="setStarred(car)">star_border
            </v-icon>
          </h2>
        </v-flex>
      </v-layout>
    </v-container>
  </v-app>
</div>

Any help will be appreciated. Thank you.

4 Answers 4

1

You have to loop throw other array items and set their starred property to false. Or, you can store a data variable to indicate the index of the object which is currently stared.

new Vue({
  el: '#app',
  data() {
    return {
      cars: [{
          name: 'Toyota',
          starred: false
        },
        {
          name: 'BMW',
          starred: false
        },
        {
          name: 'Ford',
          starred: false
        }
      ],
      lastStarredIndex: null
    }
  },
  methods: {
    setStarred(index) {
      if (this.lastStarredIndex === index) {
        // toggle same item
        this.cars[index].starred = !this.cars[index].starred;
        if (this.cars[index].starred) this.lastStarredIndex = index;
        else this.lastStarredIndex = null;
      } else {
      
          // disable last stared item
          if (this.lastStarredIndex !== null) this.cars[this.lastStarredIndex].starred = false;

          // set the new one
          this.cars[index].starred = true;
          
          this.lastStarredIndex = index;
       }
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<link rel="stylesheet"  href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'>

<div id="app">
  <v-app id="inspire">
    <v-container>
      <v-layout justify-center column>
        <v-flex xs6 v-for="(car,index) in cars" :key="index">
          <h2>{{car.name}}
            <v-icon :color="car.starred ? 'primary': '' " @click="setStarred(index)">star_border
            </v-icon>
          </h2>
        </v-flex>
      </v-layout>
    </v-container>
  </v-app>
</div>

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

Comments

1
new Vue({
  el: '#app',
  data() {
    return {
      cars: [{
          name: 'Toyota',
          starred: false
        },
        {
          name: 'BMW',
          starred: false
        },
        {
          name: 'Ford',
          starred: false
        }
      ]
    }
  },
  methods: {
    setStarred(item) {
      // Set all to false
      _.each(this.cars, function(value, key) {
          value.starred = false;
      });
      item.starred = true
    }
  }
})

Comments

1

Solution

new Vue({
  el: "#app",
  data() {
    return {
      cars: [
        {
          name: "Toyota",
          starred: false,
        },
        {
          name: "BMW",
          starred: false,
        },
        {
          name: "Ford",
          starred: false,
        },
      ],
    };
  },
  methods: {
    setStarred(item) {
      this.cars.forEach((car) => (car.starred = car.name === item.name));
    },
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />
<link rel="stylesheet"  href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'>

<div id="app">
  <v-app id="inspire">
    <v-container>
      <v-layout justify-center column>
        <v-flex xs6 v-for="(car,index) in cars" :key="index">
          <h2>{{car.name}}
            <v-icon :color="car.starred ? 'primary': '' " @click="setStarred(car)">star_border
            </v-icon>
          </h2>
        </v-flex>
      </v-layout>
    </v-container>
  </v-app>
</div>

Comments

0
<v-icon :color="car.starred ? 'primary': '' " @click="setStarred(index)">star_border
            </v-icon>

methods: {
        setStarred(index) {
          this.cars.map(i => {
            i.starred = false
          })
          this.cars[index].starred = true
        }
      }

1 Comment

Thank you brother!! this is perfect.

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.