What is the method for modifying the array that has been generated using Vue's "prop" feature?

According to the Vue documentation, a prop is passed in as a raw value that may need transformation. The recommended approach is to define a computed property using the prop's value.

If the "prop" is an array of objects, how can it be transformed into a computed array and then mutated? I followed the documentation but am unsure about mutating it.

In the example below, the component accepts an array of items

Array<{ ID: string, lettering: string; }>
. It renders buttons for each item.

  1. Clicking a button should change its color.
  2. Clicking the same button again should revert it to its initial state.

Experience it here

<template>
  <div>
    <button  
      v-for="(item, index) in selectableItems"
      :key="`BUTTON-${item.ID}`"
      :class="{ selected: item.selected }"
       @click="() => {onButtonClicked(item, index) }"
    > {{ item.lettering }}
    </button>
  </div>  
</template>

I generate the selectableItems from the items array. Each item in selectableItems has an additional property selected along with the original properties of the item.

export default {
  name: "HelloWorld",
  props: {
    items: Array
  },
  computed: {
    selectableItems: function () {
      const selectableItems = [];
      this.items.forEach((item) => {
        selectableItems.push({
          ID: item.ID,
          lettering: item.lettering,
          selected: false
        });
      });
      return selectableItems;
    }
  },
  methods: {
    onButtonClicked: function(item, index) {
      if (item.selected) {
        this.selectableItems[index].selected = false;
      } else {
        this.selectableItems[index].selected = true;
      }
      console.log(this.selectableItems);
    }
  }
};

The buttons in Vue do not re-render currently.

I understand that mutating the getter is not the right way to go. But what is the correct approach to mutate the array?

Forbidden solution

Passing the

{ ID: string, lettering: string; selected: boolean; }
via props instead of
{ ID: string, lettering: string; }
is against the rules.
{ ID: string, lettering: string; }
represents the pure model and should not contain any information about UI. selected: boolean; is strictly for UI purposes only.

Answer №1

If you're in a hurry, check out this quick example on jsfiddle https://jsfiddle.net/hgvajn5t/

To save time, I've skipped creating two components and accessed the data directly as props.

The key is to define your selected buttons in your data

data () {
    return {
      selectedItems: []
    }
},

The next step is to keep track of which items are selected and which are not

onButtonClicked: function(item){
  let index = this.selectedItems.indexOf(item.ID)
  if (index > -1) {
    this.selectedItems.splice(index, 1)
  } else {
    this.selectedItems.push(item.ID)
  }
}

The onButtonClicked function takes the item as input and toggles its selection status

Lastly, update your binding to apply the selected class based on whether the item is in the selectedItems array or not

:class="{ selected: selectedItems.indexOf(item.ID) > -1 }"

Remember, this approach works best when each item's ID is unique.

In conclusion: This method may seem complicated at first, especially for beginners in Vue. It all boils down to how you structure your UI. Remember, avoid directly manipulating props. Using computed properties to enhance them is okay, but modifying computed properties is not recommended. If you need the select state outside the current component, consider emitting events to update the data source directly from the parent component. This way, you maintain a single source of truth instead of storing extra information about the items elsewhere.

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

What are some tips for increasing your points on the journey using Here Maps?

While plotting a route, I noticed that the segments on highways are quite far apart. Is there a way to get a more detailed routing with finer points along the journey? $.ajax({ url: 'https://route.cit.api.here.com/routing/7.2/calculateroute ...

Tips for identifying when v8 heap utilization in Node.js is nearing its limit

Currently, my script includes the following code: const v8 = require('v8'); let heap = v8.getHeapStatistics(); let usage = 100 / heap.heap_size_limit * heap.used_heap_size; if (usage > 90) { console.log(`V8 heap usage close to the limit ...

Utilizing diverse values retrieved from HTML data attributes

*UPDATE Within my HTML, I have a list titled "#wordlist" that contains the words for my game, along with corresponding audio and images for each word. Everything is functioning correctly. As there will be multiple versions of the game, I've been tas ...

Tips for extracting parameters from a URL using Express JS in a custom manner

Recently, I set up a server using the express package and encountered an issue while trying to extract parameters from the URL in a specific format. The URL structure is as follows: (notice there's no '?' indicating parameters). I am lookin ...

Receive emails: using the require() function with ES Module

After following the react-email documentation, I encountered an error when trying to run the yarn email command: $ email dev --port 3001 ***\node_modules\ora\index.js:65 if (process.platform === 'win32') { ...

Interactive calendar using Php and Javascript/Ajax

Currently, I am working on a PHP calendar and have integrated Javascript/Ajax functionality to enable smooth scrolling between months without the need for page refresh. Interestingly, the calendar displayed as expected before implementing Javascript/Ajax, ...

Can the AngularJS icon adapt to different lists?

I'm currently developing in AngularJS / Jade and I need to implement functionality where an icon changes when a user clicks on something. The code I have right now looks like this: a(onclick='return false', href='#general', data-t ...

Developing a personalized Hook with useRef functionality

Here is a code snippet where I demonstrate creating two custom hooks in React. The first hook, `useChangeText`, utilizes the `useState` hook and works as expected. The second hook, `useGetHTML`, attempts to use `useRef` to log an HTML element to the cons ...

Warning: Promise rejection not handled in error

I've been working with nodejs, express, and argon2 in my project. However, I encountered an error that has left me puzzled as to why it's happening. Strangely, even though I don't have any callbacks in my code, this error keeps popping up. H ...

Next.js: Uh-oh! Looks like we've hit an obstacle with Error 413 Request Entity

I've encountered an issue while attempting to upload large files using Next.js. I've set up an onChange function for my file input, and here's the code snippet: const handleFileUpload = () => new Promise(async (resolve) => { if(ref ...

Warning users when submitting a form if required fields are left empty

As a Python developer, I have been delving into Vue.js development. I have a function similar to a() in Python that takes iterables. If all items in the iterable are true, then all([...]) returns true. methods: { all: function(iterable) { for ...

The "Splash Screen Div" page displayed during transitions and page loading

Creating a "Splash Screen Div" for a loading page involves waiting until everything is loaded and then hiding or moving the div off screen. Below is an example: index.html <div id="loading-Div"> <div id="bear-Logo"> < ...

Removing duplicate values in Vue after sorting

Explore <div v-for="todo in sortedArray"> <b-button block pill variant="outline-info" id="fetchButtonGap" v-model:value="todo.items[0].arrivalTime"> {{fromMilTime(todo.items[0].arrivalTime)}} < ...

Simple Way to Show API Output in Plain Text (Beginner Inquiry)

I'm a beginner when it comes to using APIs. I'm trying to display the plain text response from this URL on my webpage: However, I'm encountering issues with getting it to work. Here's my code: <script src="https://ajax.googleap ...

Tips for acquiring offspring who are exclusively not descendants of a particular node

Currently, I am utilizing jQuery and my goal is to access all elements of a specific type that are not children of a particular node type. For example, my Document Object Model (DOM) structure looks like this: <div id='idthatiknow'> & ...

What is the best method for typing a component prop that is compatible with singular use and can also function within loops without disrupting intellisense?

The Scenario Within a heading component, I have defined various types as shown below: // Heading/index.d.ts import { HTMLAttributes } from 'react'; export const HeadingType: { product: 'product'; marketing: 'marketing'; ...

The server's response is unpredictable, causing Json.Parse to fail intermittently

I have encountered a strange issue that is really frustrating. It all started when I noticed that my Json.Parse function failed intermittently. Here is the code snippet in question: const Info = JSON.parse(response); this.onInfoUpdate(Info.InfoConfig[0]); ...

Instructions for rendering a component after directly inserting its tag as raw HTML in Vue 3

Recently, I encountered an issue with a vue instance that contains a globally registered component in a legacy project. Due to the legacy nature of the project, it heavily relies on jsrender for rendering html post ajax requests. Despite having the compon ...

An error has occurred in the callback function for the watcher "function () { return this._data.$$state }": "Error: [vuex] It is forbidden to modify the vuex store state outside of a mutation"

Here is a screenshot of the error I encountered in the console This is the method that I am using The issue seems to be happening in mounted I have also included MapState in the Computed section While my code is currently functional, I am puzzled by th ...

Is there a way to search for a specific item within a nested array?

I have 2 arrays within an array, each containing objects. How can I locate the object with the name "Sneijder"? const players = [ [ { id: 1, name: "Hagi", }, { id: 2, name: "Carlos", }, ], [ { id: 3 ...