Vue2 - "An error has occurred: Unable to access value property of undefined"

I'm facing an issue with my custom input component in my app where I need to emit change events up to the parent and send those values to the $store using commit/dispatch. While debugging, I observed that the parent can receive the values but I am puzzled by this error message:

[Vue warn]: Error in v-on handler: "TypeError: Cannot read properties of undefined (reading 'value')"

found in

---> <CustomInput>

This error only occurs when a user is manually editing the title/subtitle fields and shows up after every keystroke. Could this be a timing error?


Custom Input Component:

<template>
  <div>
    <label for="title">Edit Title: </label>
    <input
      type="text"
      id="title"
      :updateTitle="updateTitle"
      v-model="inputTitle"
    />

    <label for="subtitle">Edit Subtitle: </label>
    <input
      type="text"
      id="subtitle"
      :updateSubtitle="updateSubtitle"
      v-model="inputSubtitle"
    />

  </div>
</template>

<script>
export default {
  name: 'CustomInput',
  props: {
    value: {
      type: Object,
      required: true,
    },
  },
  computed: {
    updateTitle() {
      console.log('updateTitle: ', this.value.title);
      return this.value.title;
    },
    updateSubtitle() {
      console.log('updateSubtitle: ', this.value.subtitle);
      return this.value.subtitle;
    },
    inputTitle: {
      get() {
        return this.value.title;
      },
      set(title) {
        console.log('setting new title: ', title);
        this.$emit('input', title);
      },
    },
    inputSubtitle: {
      get() {
        return this.value.subtitle;
      },
      set(subtitle) {
        console.log('setting new subtitle: ', subtitle);
        this.$emit('input', subtitle);
      },
    },
  },
};
</script>

Parent Component:

<template>
  <main class="home-page page">

    <div v-if="!editMode" class="display-information">
      <div class="title">
        <span class="bold">Title: </span>{{title}}
      </div>

      <div class="subtitle">
        <span class="bold">Subtitle: </span>{{subtitle}}
      </div>

      <div class="controls">
        <button id="randomize-button" class="control-button" @click="randomizeTitleAndSubtitle">
          Randomize
        </button>
        <button id="edit-button" class="control-button" @click="onEdit">Edit</button>
      </div>
    </div>

    <div v-else class="edit-controls">

      <CustomInput
        :value="{ title, subtitle }"
        @input="onSave(v = { title, subtitle }, $event.target.value)"
      />

      <div class="controls">
        <button id="cancel-button" class="control-button" @click="onCancel">Cancel</button>
        <button id="save-button" class="control-button" @click="onSave">Save</button>
      </div>
    </div>
  </main>
</template>

<script>
import CustomInput from '@/components/CustomInput.vue';
import { mapState, mapActions } from 'vuex';

export default {
  name: 'Home',
  components: {
    CustomInput,
  },
  data() {
    return {
      editMode: false,
    };
  },
  computed: {
    ...mapState(['title', 'subtitle']),
  },
  methods: {
    ...mapActions(['randomizeTitleAndSubtitle', 'updateTitleAndSubtitle']),
    onEdit() {
      this.editMode = true;
    },
    onCancel() {
      this.editMode = false;
    },
    onSave(v) {
      this.editMode = false;
      console.log('returned value object: ', v);
      this.$store.dispatch('UPDATE_TITLE', v.title);
      this.$store.dispatch('UPDATE_SUBTITE', v.subtitle);
    },
  },
  mounted() {
    this.randomizeTitleAndSubtitle();
  },
};
</script>

Answer №1

The issue is with the @input attribute:

<CustomInput
   :value="{ title, subtitle }"                     ❌
   @input="onSave(v = { title, subtitle }, $event.target.value)"
   />

CustomInput triggers the input event using a string value:

export default {
  ⋮
  computed: {
    ⋮
    inputTitle: {
      ⋮
      set(title) {            👇
        this.$emit('input', title);
      },
    },
    inputSubtitle: {
      ⋮
      set(subtitle) {          👇
        this.$emit('input', subtitle);
      },
    },
  },
};

This means that $event contains the string value, not an object with a target property, resulting in the error you are experiencing.

If you copied the code from an @input on an <input> element, $event would have been an InputEvent object.

To fix this problem:

You need to update the markup by removing .target.value:

<CustomInput
   :value="{ title, subtitle }"              ✅
   @input="onSave(v = { title, subtitle }, $event)"
   />

Check out the demo here

Answer №2

After some investigation, I managed to streamline the code related to my initial query. I inserted an empty object in the data to serve as a placeholder for the emitted object values from the custom input component. Additionally, I eliminated unnecessary code from the custom input component, emphasizing only the essentials and eliminating redundant $emit events.

Custom Input:

<template>
  <div>
    <label for="title">Edit Title: </label>
    <input
      type="text"
      id="title"
      :setTitle="setTitle"
      ref="title"
      :value="value.title"
      @input="updateValue()"
    />

    <label for="subtitle">Edit Subtitle: </label>
    <input
      type="text"
      id="subtitle"
      :setSubtitle="setSubtitle"
      ref="subtitle"
      :value="value.subtitle"
      @input="updateValue()"
    />

  </div>
</template>

...

Parent:

<template>
  <main class="home-page page">

    <div v-if="!editMode" class="display-information">
      <div class="title">
        <span class="bold">Title: </span>{{title}}
      </div>

      <div class="subtitle">
        <span class="bold">Subtitle: </span>{{subtitle}}
      </div>

    ...

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

delivering axios response to display the page

I have a code snippet that requests data from an external API using axios and I want to incorporate the response into my rendered page. Here is my code: //Snippet from my controller required in main routes exports.recordBySlug = async (req, res, next) =&g ...

Create a slider feature on a webpage using the Google Maps API

A webpage has been created using the Google Map API. JSfiddle function initMap() { var intervalForAnimation; var count = 0; var map = new google.maps.Map(document.getElementById('map'), { cen ...

Enhance click functionality on list item content using knockoutjs

Check out my app on GitHub or view it live at this link. I'm trying to implement a feature where clicking on each item, like "Bookworm Buddy," will toggle its description within the project. Here's what I've attempted so far: function AppV ...

Customizing the default image of a Select dropdown field in Sencha Touch

Does anyone know how to change the default image of a select dropdown in Sencha Touch to a customized image? I've attached a screenshot for reference but can't seem to find any properties or classes to adjust this. Any guidance would be greatly a ...

Utilizing the setInterval function within the componentDidMount lifecycle method in React

I am facing a challenge in updating the state of a React component every 1000 ms. I attempted to use setInterval in the componentDidMount method, but encountered issues. Currently, when I log the results, I see an empty state object in the constructor and ...

What prevents me from calling a function while it is being defined in the prototype?

I am experimenting with inheritance through an example. I want to access all properties of objects abc and pqr, so I decided to use Object.create. However, when I try to get the value of r by calling the getr() function, it doesn't seem to work as exp ...

I am utilizing the useEffect hook along with Axios to fetch data from the backend. My goal is to retrieve two arrays of objects in order to render them on the

I am attempting to retrieve 2 arrays of objects from my MySQL database using Axios, but the console.log output '3' is showing an empty array. I'm not sure what's causing this issue. export default function Editar() { let {clienteId} = ...

What is the best way to adjust the autoplay volume to a set level?

I have a page with an audio element that autoplays, but I want to ensure the volume is set to a specific level in case a user has their volume turned up to 100%. Any suggestions on how to accomplish this? Here's the HTML code: <audio autoplay> ...

What is the method for incorporating a variable in MapReduce?

I have the following MapReduce script that I'm working with: splitAndGroupServices = function(groupMembers) { var mapFunction = function() { for(var idx in this.services) { var service = this.services[idx]; if(service.mem ...

What is preventing the table from extending to the full 100% width?

Displayed above is an image showing an accordion on the left side and content within a table on the right side. I have a concern regarding the width of the content part (right side) as to why the table is not occupying 100% width while the heading at the ...

Attempting to display an HTML image utilizing data storage

I'm currently working on building a database for animals at an animal shelter. I have created tables containing species information and when a user selects a specific species, all available animals are displayed. Now, I want users to be able to click ...

What is the method to store anchor text in a Session variable?

I'm currently working on a project where I've linked multiple pdf files in the master page. When clicking the anchor, the page redirects to the specified location and displays the pdf in an iframe. Now, I want the text within the anchor tag to be ...

Toggle the visibility of a checkbox based on the JSON data

I have 4 check boxes that need to be dynamically displayed based on the value retrieved from my JSON. The JSON will only contain one checkbox name, and that specific checkbox should be shown to the user as checked. How can I achieve this functionality? Bel ...

The Issue of Double-Clicking on Table Cells in Internet Explorer 8

I implemented a JQuery function to add a double click event listener to a table, which triggers a modal popup when a cell is double-clicked. While this functionality works seamlessly in Firefox, there is an issue in IE8 where double-clicking a cell highli ...

The Nodejs function exits before the internal function finishes executing

Currently, I am facing an issue where despite MongoDB returning the correct number of users (more than 0) when running console.log within collection.find(), the function userExists always returns false (0). I'm seeking guidance on how to ensure that ...

There seems to be a problem with the external JavaScript file not functioning

After dragging and dropping the .js file into my ASP.NET project, I am facing an issue where it remains unresponsive, even though the code works fine when used inline. This problem is occurring while using VS 2017. Here is a snippet of my code: <scrip ...

What is the best way to design a dynamic menu using HTML, CSS, and jQuery, where each li element gradually disappears?

Consider this menu structure: <ul class="main-menu"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> </ul> My task is to dynamically hide th ...

The function _vm.$refs.menu.open is not defined

Utilizing vue-context to customize the default context menu, I encounter an error when trying to interact with it from a component. Below is my code snippet: <!-- Main --> <p @contextmenu.prevent="$refs.menu.open">test</p> <C ...

Looking to find top-notch keywords that stand out from the rest?

My chosen keyword is s='young girl jumping' function selfreplace(s) { var words = ['man', 'jumping']; var re = new RegExp('\\b(' + words.join('|') + ')\\b', 'g&a ...

Delay the axios get request in the useEffect

Working with React JS, I have implemented a useEffect hook to request data from a database via an Express server when the page renders. However, if the server is down, the app will continue to make thousands of requests until it crashes. Is there a way to ...