Upgrading object based on dynamic data shifts in Vue using Vuex

My current task involves updating data in a component based on the selection made from a tabs list at the top of the page. The data is sourced from a Vuex data store, and after conducting tests on the data store, everything appears to be functioning correctly. I have inserted dummy data into the data store which is visible in my Vue Chrome dev tools plugin.

However, upon structuring the component as outlined below and attempting to load the page, an error message

Cannot read property 'amount' of undefined
is displayed in the console. It seems like this issue arises because the data loads before the computed properties are set in Vue.

I am contemplating various approaches but am aiming to seamlessly switch the displayed data when a tab is selected. One option would involve creating a separate component for each tab, although this could lead to redundant code.


Previous Attempts

- I attempted replacing currentObj: this.obj1 with currentObj: {} in the data section, but encountered the same error.

- Moving the currentObj data property to a computed property was another approach. While this allowed the page to load, the error persisted, and selecting tabs did not update the data.


Is there a method to effectively swap out the data in currentObj within my component?

<template>
  <div>
    <ul class="tabs">
      <li class="tab-title" v-on:click="tabSelection = 'tab1'">Tab 1</li>
      <li class="tab-title" v-on:click="tabSelection = 'tab2'">Tab 2</li>
      <li class="tab-title" v-on:click="tabSelection = 'tab3'">Tab 3</li>
    </ul>
    <div>{{ currentObj.amount }}</div>
  </div>
<template>

<script>
export default {
  data: function() {
    return {
      tabSelection: 'tab1',
      currentObj: this.obj1
    }
  },
  watch: {
    tabSelection: function(oldTabSelection, newTabSelection) {
      switch (newTabSelection) {
        case 'tab1':
          this.currentObj = this.obj1;
          break;
        case 'tab2':
          this.currentObj = this.obj2;
          break;
        case 'tab3':
          this.currentObj = this.obj3;
          break;
      }
    }
  },
  computed: {
    obj1: function() {
      return this.$store.getters.obj1;
    },
    obj2: function() {
      return this.$store.getters.obj2;
    },
    obj3: function() {
      return this.$store.getters.obj3;
    }
  }
}
</script>

Answer №1

My suggestion is to update your template for safer navigation:

<template>
  <div>
    ...
    <div>{{ currentObj && currentObj.amount }}</div>
  </div>
<template>

Alternatively, you can also try:

<template>
  <div>
    ...
    <div v-if="currentObj">{{ currentObj.amount }}</div>
  </div>
<template>

Answer №2

One issue arises when currentObj becomes undefined unexpectedly. To address this symptom, we can follow the solution proposed in another response which suggests handling scenarios where obj1, and similar objects, may be missing from the store. This situation occurs if these objects are not defined at the time a tab is clicked:

An attempt was made to substitute data's currentObj: this.obj1 with currentObj: {}. However, the error persists.

Furthermore, even if obj1, etc. are present in the store, the obj1 computed property might still not be accessible in data due to the component instance being yet to be created as it depends on existing data. The lifecycles between beforeCreate and created need to run first.

A workaround entails invoking a getter:

currentObj: this.$options.computed.getNumbers.call(this)

Naturally, this may lead to complications if the computed property relies on other unavailable elements. A more appropriate approach involves explicitly defining initial data:

currentObj: this.$store.getters.obj1

To avoid such issues altogether, the component should be designed differently so that there are no problems. Removing the need for a tabSelection watcher and making currentObj a computed property instead of data would be better since its value is determined based on tabSelection:

  computed: {
    currentObj() {
      let obj;
      switch (this.tabSelection) {
        case 'tab1':
          obj = this.obj1;
          break;
        case 'tab2':
          obj = this.obj2;
          break;
        case 'tab3':
          obj = this.obj3;
          break;
      }
      return obj || { amount: 'No amount' } // in case missing objs are expected
    },
    ...

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 best method for executing computations within Vue.js 2?

Here is my second vue component: <template> <div class="row"> <div v-for="item in options"> <div class="panel panel-default panel-product"> .... </div> </div> ...

Using a ThreeJS bitmap texture to extrude a shape created with THREE.Shape

I have successfully created a cube with rounded corners using the THREE.Shape object: var shape = new THREE.Shape(); x = width/2; y = height/2; shape.moveTo(x - radius, y); //*** Top right x = -width/2; y = height/2; shape.lineTo(x + radius, y); if (tr) ...

Reacting to the surprise of TS/JS async function behaving differently than anticipated

It appears that I'm facing a challenge with the small method; not sure if my brain is refusing to cooperate or what's going on. async fetchContacts() { await this.http.get('http://localhost:3000/contacts') .subscribe(res =& ...

how can I include an AngularJS variable as a parameter in an onclick function?

I attempted to utilize an AngularJS variable as an argument value inside onclick() in order to invoke a JavaScript function. Can someone provide me with instructions on how to achieve this? Here is my code: <div onclick="deleteArrival({{filterList.id} ...

React - Issue with Input event handling when utilizing both onChange and onKeyDown functions

I was attempting to create a feature similar to a multi-select, where users could either choose a value from a list or enter a new value. The selected value should be added to an array when the user presses the enter key. To monitor changes in the input ...

Is it possible to use jQuery validate for remote parsing with two fields in a single call

Currently, I am facing an issue while trying to parse two values using jQuery's validate plugin to compare with an SQL database. The DateReceived value is successfully parsed, but the CentreID value always appears as null. Below is the code snippet I ...

Grab the table headings from an HTML table and store them in variables after accessing the DOM

Looking to modify the structure of the DOM. Wanting to display table content using paragraphs instead. To achieve this, I need to extract data from each row in the table. How can I accomplish this task? <table style="width:300px"> <tr> ...

Unlocking the potential of the ‘Rx Observable’ in Angular 2 to effectively tackle double click issues

let button = document.querySelector('.mbtn'); let lab = document.querySelector('.mlab'); let clickStream = Observable.fromEvent(button,'click'); let doubleClickStream = clickStream .buffer(()=> clickStream.thrott ...

Creating crypto.createCipheriv arguments from fixed origins

Currently, I am implementing a code snippet in my node.js application to perform string encryption. I am seeking guidance on how to create the KEY and HMAC_KEY from a predetermined source. At the moment, these keys are randomly generated within the progra ...

Encountered an issue running "npm install" within the Vue3 composition API

Encountering an error while trying to install dependencies in a Vue3 project. npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-c ...

Providing a public API that exclusively grants access to requests originating from my own website

After hours of scouring Google and SO, I have yet to find someone facing the same challenge I am encountering now. Here's the situation: We have invested a significant amount of money and effort into maintaining a database. The data from this databas ...

Display additional information from a JSON file after choosing an ID with AngularJS Select

After saving a JSON file filled with information, I managed to successfully populate a select menu with the names of each element from the JSON data using this code snippet: <select ng-model="car.marca" ng-options="item.brakeId as item.name for item in ...

Using plain JavaScript (without any additional libraries like jQuery), you can eliminate a class from an element

I'm attempting to locate an element by its class name, and then remove the class from it. My goal is to achieve this using pure JavaScript, without relying on jQuery. Here is my current approach: <script> var changeController = function() { ...

When using the * selector in jQuery on Chrome, it targets and selects scrollbars

Here's the code I'm currently using: $("*").bind("mousedown.sg", { 'self':this }, this.sgMousedown); This code binds an event listener to all elements on the page, and it functions properly in most browsers except for Chrome. In Chrom ...

Determining if the current URL in NextJS is the homepage

Just getting started with NextJS. I am trying to determine if the current URL is the home page. When I use: import { useRouter } from "next/router"; const router = useRouter(); const is_home = (router.pathname === ''); An error pops ...

Submit form data asynchronously using Ajax and serialize the form data before posting

I'm currently facing an issue with posting HTML form values in my code. Everything works fine except for the fact that I can't get it to post single quotes ' . I believe this problem is caused by the usage of serialize. I've attempted c ...

"Encountered a floating-point issue when trying to read an Excel file with

When a user uploads an Excel file that contains decimal, string, and Unicode characters, I am encountering an issue with floating point errors when reading certain decimal values. For instance, a number like 0.15 is being read as 0.150000000002 in some c ...

"eliminate" ng-if after the condition becomes true

I'm curious to know if it's possible to deactivate or remove ng-if once its value becomes true? In my project, I've constructed a tree structure using a recursive directive. Each branch in the tree has a <div ng-if="visible"> element ...

How can I simulate or manipulate the element's scrollHeight and clientHeight in testing scenarios?

In my JavaScript code, I have a function that checks if an HTML paragraph element, 'el', is a certain size by comparing its scrollHeight and clientHeight properties: function isOverflow(element: string): boolean { const el = document.getEleme ...

Discovering the key to selecting a row by double-clicking in Vuetify's v-data-table

I'm having trouble retrieving the row by event in my v-data-table. It only gives me the event and remains undefeated. How can I catch items in the v-data-table? <v-data-table :headers="showHeaders" :page="page&quo ...