Somethingwhatever
Somethingwhatever

Reputation: 1368

Toggle property of an object in an array VueJS?

I am trying to create a user feedback form where users can rate the quality of the food item they ordered. I have an array foodItems which render the food list and i have certain reactions set up for the food items. I am trying to add a method so that user can provide the feedback but user can set up only one reaction at a time. So for instance for Pizza they can be satisfied or dissatisfied and the selected reaction should be highlighted and so on but i am not sure how i can do it.

Check out this sample codepen.

Check out this working example:-

new Vue({
  el: "#app",
  data() {
    return {
      reaction: false,
      selectedReaction: "",
      foodItems: [{
          name: "Pizza",
          value: "pizza"
        },
        {
          name: "Pasta",
          value: "pasta"
        }
      ]
    };
  },
  methods: {
    setReaction() {
      this.reaction = !this.reaction;
    }
  }
});
<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 rel="stylesheet"  href='https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons'>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet" />

<div id="app">
  <v-app id="inspire">
    <v-container>
      <v-layout row wrap justify-center>
        <v-flex xs6 v-for="(food,index) in foodItems" :key="index">
          <h1>{{ food.name }}</h1>
          <v-icon large left :color="reaction ? 'primary' : ''" @click="setReaction">sentiment_dissatisfied</v-icon>
          <v-icon large :color="reaction ? 'primary' : ''" @click="setReaction">sentiment_very_satisfied</v-icon>
        </v-flex>
      </v-layout>
    </v-container>
  </v-app>
</div>

So basically i am trying to add the functionality for the users to rate the food. Any help will be appreciated. Thank you so much.

Upvotes: 1

Views: 478

Answers (3)

Paridhi Jain
Paridhi Jain

Reputation: 190

The main concern is you need to have a reaction corresponding to each food item, so add a reaction/feedback property with each food item. Notice individual feedback change. There can be so many other approaches as well.

    https://codepen.io/pjain-techracers/pen/abvXPwK

Upvotes: 1

Riccardo Manzan
Riccardo Manzan

Reputation: 823

The simplest thing to do is using a boolean value like isSatisfied which is false if user dissatisfiedm true if it is satisfied and undefined if no information has been given.

the problem with this is that if you write if(isSatisfied) and the flag is undefined, codeflow goes to else block. so you should write something like

if(isSatisfied)
     //satisfied
if(isSatisfied === false)
     //unsatisfied

Another option is to use a string, you can store a string feedback that can be undefined, 'satisfied' or 'unsatisfied'.

You can do the same using a number.

Those last options are more flexible as you can "upgrade" feedback system without changing the model (obviously within certain limits).

That flags/strings/numbers must be stored somewhere. You could create a new feedback array of objects, each of them containing:

  • food reference

  • user reference

  • user rating

Upvotes: 3

Ashish
Ashish

Reputation: 4330

There are many approaches for this, but in the end what you need to do is, store rating for every food item.

What I have done in my implementation is created an array for ratings selectedReaction, which will store either 1, -1, undefined. Whenever you add any rating, for any food, for the index of food in foodItems I add 1 for positive feedback, -1 for negative feedback at the same index in selectedReaction.

<div id="app">
<v-app id="inspire">
    <v-container>
    <v-layout row wrap justify-center>
        <v-flex xs6 v-for="(food,index) in foodItems" :key="index">
        <h1>{{ food.name }}</h1>
        <v-icon large left :color="selectedReaction[index] === -1 ? 'primary' : ''" @click="setReaction(index, false)">sentiment_dissatisfied</v-icon>
        <v-icon large :color="selectedReaction[index] === 1 ? 'primary' : ''" @click="setReaction(index, true)">sentiment_very_satisfied</v-icon>  

        </v-flex>
    </v-layout>
    </v-container>
</v-app>
</div>


new Vue({
    el: "#app",
    data() {
    return {
        selectedReaction: [],
        foodItems: [
        {
            name: "Pizza",
            value: "pizza"
        },
        {
            name: "Pasta",
            value: "pasta"
        }
        ]
    };
    },
    methods: {
    setReaction(index, isSatisfied) {
        const reaction = [...this.selectedReaction];
        reaction[index] = isSatisfied ? 1 : -1;
        this.selectedReaction = reaction;
    }
    }
});

Upvotes: 3

Related Questions