Establishing Accessor and Mutator Methods

The variables startStopA... and InitialValueA... that were originally in the component TableFields.vue need to be relocated to the store file index.js. However, upon moving them to the store, an error appears stating that setters are not set. I have extensively consulted the documentation and attempted various solutions, but I have been unsuccessful in resolving the issue.

Component TableFields.vue

<template>
  <div>
    <div class="wrapper" v-for="(field, index) in fields" :key="index">
      <table>
        <tr>
          <th>{{ field }}</th>
          <td class="sign">{{ randomSign[index] }}</td>
          <td class="value">{{ initialValues[index].toFixed(2) }}</td>
          <td v-show="$store.state.randomSign[index] === '+'">&#x2B06;</td>
          <td v-show="$store.state.randomSign[index] === '-'">&#x2B07;</td>
        </tr>
      </table>

      <button
        @click="toggleInterval(field)"
        v-if="field === 'A'"
        :class="[startStopA ? 'button-start' : 'button-stop']"
      >
        <span v-show="startStopA">Stop</span>
        <span v-show="!startStopA">Start</span>
      </button>

      <button
        @click="toggleInterval(field)"
        v-if="field === 'B'"
        :class="[startStopB ? 'button-start' : 'button-stop']"
      >
        <span v-show="startStopB">Stop</span>
        <span v-show="!startStopB">Start</span>
      </button>

      <button
        @click="toggleInterval(field)"
        v-if="field === 'C'"
        :class="[startStopC ? 'button-start' : 'button-stop']"
      >
        <span v-show="startStopC">Stop</span>
        <span v-show="!startStopC">Start</span>
      </button>
    </div>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex';

export default {
  name: 'TableFields',
  data () {
    return {
      startStopA: true,
      startStopB: true,
      startStopC: true,
      initialValueA: 3,
      initialValueB: 3,
      initialValueC: 3,
      arraysInterval: null
    };
  },
  computed: {
    ...mapState([
      'changes',
      'timer',
      'fields',
      'signs',
      'randomSign',
      'randomNumbers'
    ]),

    initialValues () {
      let array;
      array = [
        this.initialValueA,
        this.initialValueB,
        this.initialValueC
      ];
      return array;
    }
  },
  methods: {
    ...mapMutations(['replaceNumbersArray']),

    toggleInterval (field) {
      // button toggle
      if (field === 'A') {
        this.startStopA = !this.startStopA;
        if (this.startStopA) {
          this.timer[0] = setInterval(() => {
            this.calculations('A');
          }, 2000);
        } else {
          clearInterval(this.timer[0]);
        }
      }
      if (field === 'B') {
        this.startStopB = !this.startStopB;
        if (this.startStopB) {
          this.timer[1] = setInterval(() => {
            this.calculations('B');
          }, 2000);
        } else {
          clearInterval(this.timer[1]);
        }
      }
      if (field === 'C') {
        this.startStopC = !this.startStopC;
        if (this.startStopC) {
          this.timer[2] = setInterval(() => {
            this.calculations('C');
          }, 2000);
        } else {
          clearInterval(this.timer[2]);
        }
      }
      if (!this.startStopA && !this.startStopB && !this.startStopC) {
        clearInterval(this.arraysInterval);
      }
    },
    calculations (field) {
      this.fields.forEach((value, index) => {
        if (field === value) {
          this.randomSign[index] = this.signs[
            Math.floor(Math.random() * this.signs.length)
          ];
          const date = new Date();
          const newChange = [];

          newChange.field = field;
          newChange.indicator = this.randomSign[index];
          newChange.value = this.randomNumbers[index];
          newChange.time = date.toLocaleTimeString();

          this.changes[index].push(newChange);
        }
      });

      if (field === 'A') {
        this.randomSign[0] === '+'
          ? (this.initialValueA += this.randomNumbers[0])
          : (this.initialValueA -= this.randomNumbers[0]);
      }

      if (field === 'B') {
        this.randomSign[1] === '+'
          ? (this.initialValueB += this.randomNumbers[1])
          : (this.initialValueB -= this.randomNumbers[1]);
      }

      if (field === 'C') {
        this.randomSign[2] === '+'
          ? (this.initialValueC += this.randomNumbers[2])
          : (this.initialValueC -= this.randomNumbers[2]);
      }
    }
  },
  beforeUpdate () {
    const array = [this.startStopA, this.startStopB, this.startStopC];
    array.forEach((value, index) => {
      if (!value) {
        clearInterval(this.timer[index]);
      }
    });
  },
  mounted () {
    console.log(`${this.changes}`);
    this.arraysInterval = setInterval(this.replaceNumbersArray, 2000);

    this.fields.forEach((value, index) => {
      this.timer[index] = setInterval(() => {
        this.calculations(value);
      }, 2000);
    });

    this.initialValueA = this.$root.initialValueA || 3;
    this.initialValueB = this.$root.initialValueB || 3;
    this.initialValueC = this.$root.initialValueC || 3;

    this.startStopA = !this.$root.startStopA || !this.startStopA;
    this.startStopB = !this.$root.startStopB || !this.startStopB;
    this.startStopC = !this.$root.startStopC || !this.startStopC;

  },
  beforeDestroy () {
    clearInterval(this.arraysInterval);

    this.$root.initialValueA = this.initialValueA;
    this.$root.initialValueB = this.initialValueB;
    this.$root.initialValueC = this.initialValueC;

    this.$root.startStopA = !this.startStopA;
    this.$root.startStopB = !this.startStopB;
    this.$root.startStopC = !this.startStopC;

    this.timer.forEach(value => {
      clearInterval(value);
    });
  }
};
</script>

File store/index.js:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    changes: [],
    timer: [0, 0, 0],
    fields: ['A', 'B', 'C'],
    signs: ['+', '-'],
    randomSign: ['+', '+', '+'],
    randomNumbers: []
  },
  mutations: {
    replaceNumbersArray (state) {
      // Replaces random A, B, C... numbers at specified time intervals
      const A = Number((Math.random() + 1).toFixed(2)); // first number A
      const B = Number((Math.random() + 1).toFixed(2)); // first number B
      const C = Number((Math.random() + 1).toFixed(2)); // first number C
      state.randomNumbers.splice(0, 3, A, B, C);
      console.log(state.randomNumbers);
    }
  }
});

export default store;

GitHub repository:
https://github.com/SrdjanMilic/Super-Dynamic-Data

Codesandbox link:
https://codesandbox.io/s/super-dynamic-data-djpxe

Answer №1

If you wish to change a computed property in Vuejs, it is essential to create a setter for each property that needs mutation because computed properties are typically read-only:

According to the VueJS documentation:

Computed properties are usually for getting values only, but setters can be provided when necessary

The example of a computed property with both getter and setter functions would look something like this (as shown in the VueJS docs):

fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }

In order to make mutations reusable within your codebase, I suggest implementing them as store actions or mutations and then triggering them from your component methods (or using mapActions...etc).

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

Calculate the number of days required for the value in an item to multiply by two

I'm currently working on a JavaScript project to create a table displaying the latest number of coronavirus cases. I've reached a point where I want to add a column showing how many days it took for the confirmedCases numbers to double. Here&apos ...

Vue.js development processes are running smoothly, but experiencing issues with building and previewing the

I am working on a Vite + Vue.js 3 project in TypeScript. When I run npm run dev and go to http://localhost:5173/, everything works fine. But when I run npm run build && npm run preview and visit http://localhost:4173/, the website gives me a JavaScript err ...

Unlock the lightbox and send the user to the parent page

Is there a way to simultaneously launch a lightbox popup and redirect the parent page? I have an AJAX script that retrieves HTML content as a response. My goal is to display this content in a lightbox popup while also directing the parent window to a des ...

Working with Three.js: Retrieving an object post-loading using GLTF Loader

Is there a method in three.js using the GLTF loader to access an object for transformations after it has been loaded? It seems like attempting this approach does not yield results gltf.scene.position.set(10,10,10) Sample Code: function getObject(){ ...

Retrieve JavaScript functions as JSON or text in AngularJS and execute them

Currently, I am working on developing an AngularJS application and have come across a particular challenge that needs to be addressed: After making a web service call, I receive JavaScript code that looks like this: { "script":"function foo(a, b) { c = ...

The value returned by $(this).next() is undefined

I'm struggling to implement jQuery functionality to toggle the display of a div, but I am encountering an issue where my jQuery code is unable to select it. Every time I try, it returns undefined. Can anyone provide assistance? $(document).on(&apos ...

Error encountered in Express middleware: Attempting to write private member #nextId to an object that was not declared in its class

Currently, I am in the process of developing a custom logger for my express JS application and encountering an issue. The error message TypeError: Cannot write private member #nextId to an object whose class did not declare it is appearing within my middle ...

Is there a way to deactivate the minutes input feature in the Angular UI Timepicker?

I am using a plugin that displays the time in hours and minutes. However, I only need to show the hours. Is there a way to hide the minutes block? This is my HTML code: <uib-timepicker ng-model="mytime" ng-change="changed()" hour-step="1" minute-step ...

Executing jQuery script on dynamically loaded content

My website utilizes AJAX requests to load pages dynamically. One specific page includes a marquee script that I would like to implement. Unfortunately, due to the dynamic loading of the page, the marquee script is not functioning as expected. I have come ...

dynamically import a variety of components in vue.js and nuxt depending on certain conditions

Is there a way to implement dynamic imports for all 3 components in this scenario? Each component has different props, so using the switch option in the computed method is not feasible. I have come across solutions for using a single component dynamically ...

Arranging the Bars in a Bar Chart Using Chart.JS

Lately, I've been playing around with ChartJS and encountering an issue with sorting the bars in descending order, from lowest to highest. Despite my efforts to troubleshoot, I haven't had any success in resolving it. ...

Utilizing MeshPhongMaterial in THREE.js for Particle Material with Size Adjustment

My goal is to create particles that exhibit the characteristics of a Phong material, which means they react to light. I have been using the "createMultiMaterialObject" method to achieve this, and it has worked well for the most part. However, I have encoun ...

Adjust Fabric js Canvas Size to Fill Entire Screen

Currently, I am working with version 4.3.1 of the Fabric js library and my goal is to adjust the canvas area to fit its parent div #contCanvasLogo. I have tried multiple approaches without success as the canvas continues to resize on its own. Below is the ...

Vue3: Implementing function overrides using the Composition API

Consider a composable function as shown below: // composable/useShareComp.ts export function useShareComp() { const toto = "hey"; const tata = ref(0); function utilMethod() { console.log("Util Méthod !!"); } function mai ...

Having trouble with the functionality of expanding rows in Kendo grid

I am facing an issue with my Kendo grid that is populated from a SQL database. The expand feature works perfectly and displays a different Kendo grid in the expanded row when the program is first launched. However, if I perform a new search and get differe ...

Scrolling jqgrid to focus on the current day column and implementing a blinking effect on cells with stored data

I have a jqgrid with 38 columns of data, where the first 6 columns are frozen and the rest are unfrozen. Depending on the combo box selection, it shows either dates or months (see sample image here). After loading the grid, I want it to automatically scrol ...

I aim to move my b-card element forward within a component

My b-card component from the bootstrapvue framework is not displaying as expected. Can anyone help me figure out what I'm doing wrong? BlankBody is a versatile component that features a background ideal for multiple views. <template> <div&g ...

Activate a function when the v-data-table in Vuetify is expanded and then collapsed

While trying to create a v-data-table, I came across some odd behavior when monitoring the expanded.sync value. The first layer's expanded.sync value seems normal, but the second layer's expanded.sync has three consecutive identical records. I w ...

Issue with Bootstrap Carousel Interval Setting not Functioning as Expected

I recently added Twitter Bootstrap-Carousel to a website with the intention of using it to navigate through different sections of a module. However, I'm encountering an issue where setting the interval to false does not work as expected. When I set an ...

Encountering an issue with double quotes formatting in Spring Boot applications

Currently, I am developing an application where I need to pass data from a Spring Boot controller to a template using Thymeleaf. Everything was going smoothly, until I encountered an issue when trying to send JSON data. I noticed that the double quote (" ...