Adjusting an element within an array obtained from a computed property

Within my Vuex store, I retrieve an array of rooms from a Firebase/Firestore API call. This array structure is as follows:

[{label:'Kitchen', description:'...'}, ...]
. To make this array accessible to my application, I utilize a Vuex getter function. Subsequently, in my components, I receive this array as a computed property. However, in my CRUD component, I route this "original" array through another computed property to attach various temporary properties to each object in the array -
workable: () => this.rooms.map(val => { return ...val, editing: false, loading:false, ... })
. It's important to note that these additional properties are specific to the CRUD component and are not intended to be kept on the original array, the data source, or anywhere else within the app.

The current issue I am facing is related to updating these temporary properties in the CRUD array. Due to my understanding (or lack thereof), it seems that my computed properties would require setters to update the original array in the Vuex store. Consequently, this would prompt updates to propagate all the way back to the data source, completing a loop. (Please correct any misconceptions or inaccuracies in this explanation.)

Therefore, my question revolves around how I can update the temporary properties within the objects in my array without causing these changes (and properties) to cascade back to the data source?

I've provided a simplified version of my code below for better visualization:

// store.js (Vuex)
const actions = {
  load: ({ commit, getters }) => {
    const query = firebase.roomCollection.where('user', '==', getters.user.id);
    const unsub = query.onSnapshot(snap => {

      const rooms = snap.docs.map(val => {
        return {
          id: val.id,
          ...val.data(),
          timestamp: val.data().timestamp.toDate(),
        };
      });

      commit('setRooms', rooms);
    });
  },
};

const mutations = {
  setRooms: (state, payload) => state.rooms = payload,
};

const state = {
  rooms: [],
};

const getters = {
  rooms: state => state.rooms,
};

// RoomCrud.vue
<template>
  <ul>
    <li v-for="room in workable" :key="`room-${i}`">
      {{ room.label }}
      <button @click="room.editing = !room.editing">Edit</button>
      <br />
      room: {{ room }} <!-- room.editing doesn't change when the Edit button gets clicked -->
    </li>
  </ul>
</template>

<script>
  import { mapGetters } from 'vuex';

  export default {
    computed: {
      ...mapGetters(['rooms']),
      workable() {
        return this.rooms.map(val => {
          return {
            ...val,
            editing: false,
            loading: false
          };
        });
      }
    }
  }
</script>

I attempted to define workable as an initially null data property and employ a method (setWorkable()) to add the extra properties to each item in the array. On mounted(), I called setWorkable(), effectively separating workable from

rooms</code. However, the drawback of this approach is the necessity to repeatedly call <code>setWorkable()
whenever a modification is made to one of the objects in the array that should ultimately reflect back to the source data.

While I understand this may be the only viable solution, I am hopeful there might exist a more efficient method using solely computed properties, thereby eliminating the need for manual re-rendering whenever a change occurs.

Feel free to request any additional details if necessary.

Answer №1

My recommendation is to adjust the approach by centralizing the logic in the store through the addition of an action called edit. This action will be triggered when the button is clicked, passing the room index and altering the row state:

// Revised store.js (Vuex)
const actions = {
 edit:({commit,state},index)=>{
     commit('editRoom', index);
  },
  load: ({ commit, getters }) => {
    const query = firebase.roomCollection.where('user', '==', getters.user.id);
    const unsub = query.onSnapshot(snap => {

      const rooms = snap.docs.map(val => {
        return {
          id: val.id,
          ...val.data(),
            editing: false,
            loading: false,
          timestamp: val.data().timestamp.toDate(),
        };
      });

      commit('setRooms', rooms);
    });
  },
};

const mutations = {
  setRooms: (state, payload) => state.rooms = payload,
   editRoom:(state,index)=> {
          state.rooms[index].editing=!state.rooms[index].editing;
           Vue.set(state.rooms,index,state.rooms);


       }
};

const state = {
  rooms: [],
};

const getters = {
  rooms: state => state.rooms,
};

RoomCrud.vue

<template>
  <ul>
    <li v-for="(room,i) in rooms" :key="`room-${i}`">
      {{ room.label }}
      <button @click="edit({index:i})">Edit</button>
      <br />
      room: {{ room }}
    </li>
  </ul>
</template>

<script>
  import { mapGetters,mapActions } from 'vuex';

  export default {
    methods:{
            ...mapActions(["edit"]),
        } ,
    computed: {
      ...mapGetters(['rooms']),

    }
  }
</script>

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 is the method for obtaining the values from these newly generated text fields?

Every time I click on the "ADD TEXTBOX" button, a new HTML textbox is dynamically created using jQuery's append method. However, I am struggling to figure out how to retrieve and store the values of these textboxes in PHP. $(w).append('<div&g ...

Creating a visual representation of the information stored in my JSON data file using a Quasar table

As a VueJS student, I'm struggling to display the distances from my JSON file in a table. What is the best way to retrieve and show all the distance data for "5" and "10" by both walking and driving? Should I use this code: this.concurrentsRows = JSO ...

Prevent the Stop Function from being executed repeatedly while scrolling

I have implemented infinite scrolling in my react/redux app. As the user nears the bottom of the page, more contents are loaded dynamically. However, a challenge arises when the user scrolls too fast and triggers the function responsible for fetching cont ...

I'm encountering problems when attempting to display the image/png response from an xmlHTTPRequest. Instead of the correct data, I

I have implemented the following code to integrate a captcha generating web service. The response data is successfully obtained, but when I attempt to display the result within a div element, the image appears as distorted text. var xmlHttp = new XMLHtt ...

AngularJS requires that JSON object property values be converted to strings in order to be displayed as actual templates

Each tab click accesses a json array containing unique templates such as ui-grid or c3 chart directive (c3.js). When a specific tab is clicked, the template in string format must be rendered into actual templates like ui-grid, c3-chart, etc. var sampleJs ...

In my specific scenario, what is the most effective method for retrieving data from an EntityFramework database using JavaScript?

Currently, within my ASP.NET MVC Core2 project, I have a model in the EF database that contains multiple properties: public class SchoolEvents { public long ID { get; set; } [Required] [StringLength(40, ErrorMessage = "Max 40 c ...

AngularJS options for selecting items: radio buttons and checkboxes

I am currently working on creating a concatenated string based on the selection of radio buttons and checkboxes. There are two radio button groups and one checkbox group. One of the radio button groups is functioning correctly, but the other automatically ...

Assign the two values to variables in the CSS script

My challenge lies in passing two values to the CSS within the <style> tags. The values are: (background-color: --placeholder; color: --placeholdtext;). I am able to pass either one of the values successfully, but not both at the same time. When I cop ...

There seems to be an issue with the post request to a PHP file as it is returning a null value when

I have been struggling with this issue for a while now and can't seem to understand why I keep getting null after calling my $.ajax function. I pass an associative array containing the method name, then invoke the method in PHP to return a JSON string ...

Is it possible to dynamically create and add new partitions to an existing topic in Node.js?

I am currently utilizing the "kafka-node" module to communicate with a kafka server, but I am unable to determine how to increase the number of partitions in an existing topic. For instance, I need to modify it from 4 partitions to 5. ...

Leverage JavaScript to update the name of a Google Spreadsheet using the latest data

Here is some code that allows you to rename a document: function renameFile() { var s = SpreadsheetApp.getActiveSpreadsheet(); s.rename("new file name"); } Can you modify this function to rename the file to "new filename 1/18"? Remember, where 18 r ...

Using Grails, the event listener can be triggered by a change in the

Looking for some advice on implementing a dynamic textfield element in a Grails form. I'm using the remoteFunction action to call a template, but unfortunately, the template is not being called as expected. When I switch from "g:textField" to "g:selec ...

Choose multiple children and grandchildren by checking the root checkbox multiple times

jquery/javascript $('.ic_parent').change(function(){ var id = $(this).attr('value') while (id.length >0){ if ($(this).attr('checked')) { $('#update_ics_table').find('input:checkbox[id = "child- ...

Pause until the existence of document.body is confirmed

Recently, I developed a Chrome extension that runs before the page fully loads by setting the attribute "run_at": "document_start". One issue I encountered is that I need to insert a div tag into the body of the webpage as soon as it is created. However, a ...

Guide to implementing CRUD operations on a remote MongoDB using Node.js

Recently, I delved into the world of NodeJS and discovered its server-side capabilities. My current project involves interacting with MongoDB on a remote server using the nodejs mongodb driver. With just a few lines of code, I am able to connect to the dat ...

The Perfect Scrollbar feature is not functioning properly in conjunction with the accordion menu

I am having some trouble with implementing the Perfect Scrollbar alongside an accordion slider menu. The scrollbar is not working as expected, and you can view the fiddle here. On initial page load, the scrollbar only appears for the first sub-menu aft ...

problem with the video pathway in the javascript document

I'm currently in the process of putting together a Video gallery playlist using HTML, CSS, and JavaScript. So far, I've set up the html and css files along with two js files. The first js file contains all the video information as shown here: ...

It ceases to function when transferred to another file

I have a function written in coffeescript that goes like this: _skip_version = (currentVersion, skippedVersions) -> if (currentVersion.indexOf(skippedVersions) == -1) return false return true This function is currently located in my archive.sp ...

Enumeration field with Conditional logic

I am currently developing a Content Management System (CMS) using strapi for a client, and I want to provide them with the ability to control the questions included in a questionnaire. Each question will be categorized under different sections in the quest ...

Replace the facebook plugin using JQuery libraries

Does anyone know how to remove the like button on top of the 'Like box' Facebook plugin using JQuery? I have imported the like box from Facebook and I want to eliminate this like button, but Facebook does not allow me to do so. Therefore, I am t ...