How to assign a property to an object within an array in VueJS?

Currently, I am creating a small list that includes car companies with an option for users to select their favorite one. Within this list, there is an array of objects containing the name and a property called starred. I have a method named setStarred which allows users to set the starred property of the selected item to true.

The issue I am facing is that I want users to be able to only select one item at a time. For example, if I select BMW, all other items should have their starred property toggled to false. Currently, I can toggle the starred property of all items simultaneously.

You can view a working example on CodePen.

Here is an example of the code:

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/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7e080b1b0a1718073e4f504b504f4a">[email protected]</a>/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f4828191809d928db4c5dac1dac5c0">[email protected]</a>/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>

Your assistance in resolving this issue will be highly appreciated. Thank you.

Answer №1

To set the starred property of other array items to false, you need to iterate through them in a loop. Alternatively, you could use a data variable to keep track of the index of the currently starred object.

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/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1d6b687869747b645d2c3328332c29">[email protected]</a>/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4c3a392938252a350c7d6279627d78">[email protected]</a>/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>

Answer №2

const myVueApp = new Vue({
  el: '#app',
  data() {
    return {
      vehicles: [{
          brand: 'Toyota',
          starred: false
        },
        {
          brand: 'BMW',
          starred: false
        },
        {
          brand: 'Ford',
          starred: false
        }
      ]
    }
  },
  methods: {
    setStarredVehicle(item) {
      // Reset all stars to false
      _.each(this.vehicles, function(value, key) {
          value.starred = false;
      });
      item.starred = true
    }
  }
})

Answer №3

Resolution

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/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="780e0d1d0c111e013849564d56494c">[email protected]</a>/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a9dfdcccddc0cfd0e998879c87989d">[email protected]</a>/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>

Answer №4

<v-icon :color="car.favorited ? 'blue' : '' " @click="toggleFavorite(index)">favorite_border
            </v-icon>

methods: {
        toggleFavorite(index) {
          this.items.map(item => {
            item.favorited = false;
          });
          this.items[index].favorited = true;
        }
      }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The jQuery Code in My Updated HTML Is Not Running Properly

Currently, I am working on a dynamic insert form for my website. In order to achieve this, I am creating a button to append a new textbox that is supposed to be using the Select2 plugin. However, when I use the jQuery append() function, the appended code d ...

a single function spread across two controllers[JavaScript]

My query pertains to a JavaScript program with 2 controllers. The issue I am facing is the need for one function in both controllers (data.duration). This function serves two purposes, once for features themselves and once for the summary. Currently, this ...

The custom element is unfamiliar: Have you properly registered the component? Vue.js in Laravel

I encountered this problem: Unknown custom element - did you register the component correctly? I am trying to implement a like system using Vue.js. Can someone please guide me on how to fix this issue? Despite my best efforts, it seems like everything is i ...

ways to invoke javascript function on body loading

I'm struggling to invoke a JavaScript function when the body loads. Currently, I have the function call on a button but cannot get it to work when added to the body load event. HTML: <body onload="bodyload();"> JavaScript: function bodyload( ...

Guide to creating a secure login page with the help of cookies

I'm in need of a quick guide on how to implement a login page for a website using cookies. Every user has a unique username and password. Is it necessary to store both the username and password in the cookies, or is just the username sufficient? Is ...

What is the method to remove an authentication code from a JSON file using JavaScript?

Is there a way to delete something from a JSON file? Here is an example: The file I am working with is named test.json Before I delete the authentication code: { "auth": [ { "test": 944037 }, { "tester& ...

I am facing an issue where the PHP header redirection stops working after implementing event.preventDefault() on form submission

After successfully implementing jQuery in my signup page to handle and check the form fields, I encountered an issue where the header("location: ../****.php") no longer redirected me to another page upon clicking submit. Instead, it loaded the new page on ...

Defining types for functions that retrieve values with a specified default

My method aims to fetch a value asynchronously and return it, providing a default value if the value does not exist. async get(key: string, def_value?: any): Promise<any> { const v = await redisInstance.get(key); return v ? v : def_value; } W ...

Implementing Tag Manager in Vue.js: A Step-by-Step Guide

I'm facing an issue with my vue.js project. I have a function that needs to be added to the head of my project. However, when I tried adding it to index.html, which is where the function (a tagManager creation) belongs, it didn't work properly. T ...

What is the number of steps jQuery animates in?

Exploring my creative side, I decided to create my own custom animate function. Struggling to achieve a seamless animation effect, unlike the smooth transitions produced by jQuery. I'm curious about the formula they utilize to determine the ideal num ...

Adjusting Header Size While Scrolling in Angular

Looking for assistance with AngularJS regarding handling events (specifically scrolling). I am trying to dynamically change the size of the header based on whether the user scrolls up or down. Below is a snippet of JavaScript code that achieves this effect ...

Annoying jQuery animation error: struggling to animate smoothly and revert back. Callback function conundrum?!

I'm completely lost with what I have accomplished. My goal was to create an animation where an element slides in from a certain position and then slides back when another element is clicked. To achieve this, I included the second event within the call ...

Script for migrating MongoDB attributes to an array

I am in the process of creating a database migration, and the current structure is as follows: { "site" : { "name" : "siteName1" }, "subStages" : [ "subStage1", "s ...

Enhance every ajax post request using jQuery

I want to include a csrf token from cookies in all my ajax posts. I've attempted the following: $.ajaxPrefilter(function(options, originalOptions, jqXHR) { if(options.type.toUpperCase() === "POST") options.data = options.data || {}; ...

Controller unable to properly increment values

$scope.isChecked = function(id){ var i=0,j=0,k=0; //$scope.abc[i].usertype[j].keywords[0].key_bool=true; if($scope.abc[i].type_selected == true){ while($scope.abc[i].usertype.length){ while($scope.abc[i].userty ...

Is there a way to trigger an Ajax function after individually selecting each checkbox in a list in MVC 4 using Razor syntax?

Is it possible to trigger an AJAX function when a checkbox within the ul below is checked? Each checkbox has a unique name attribute, such as chkbrand_1, chkbrand_2, chkbrand_3, etc. I am able to obtain the correct value using this code: $('.sear ...

Extracting object properties and tallying their occurrences

How can I extract a single property from an array of objects like the following: [{"name":"Bryan","id":016, "counter":0}, {"name":"John","id":04, "counter":2}, {"name":"Alicia","id":07, "counter":6}, {"name":"Jenny","id":015, "counter":9}, {"name":"Bryan" ...

React MUI: Dynamic and Adaptive sidebar

I'm currently working on integrating React Material UI: Persistent + Responsive drawer to create a responsive layout for mobile devices with a persistent drawer for larger screens. I've come across some code that almost fits my requirements, but ...

Passing form data to a different route using express

I need to send the data from this form, located on the index.ejs page, to another page "/rentingForm" for rendering at the "rentingForm" page. Here is the snippet of code from my app.js file: app.use(bodyParser.urlencoded({ extended: true })); app.use( bo ...

Is it possible to save the project by generating incremental JSON diffs?

In the process of developing a web-based paint program, I have implemented a system where the user's artwork state is saved as a json object. Each time an addition is made to the client's undo stack (which consists of json objects describing the ...