Vue.js: Why Objects are Returning 'Undefined' Values in Arrays

Attempting to improve my JavaScript OOP skills, I am also delving into learning vue.js. My current project involves creating a simple task list for practice purposes. While most of it is complete, I have hit a roadblock with the remove task function. Initially, I used the .remove() method but encountered issues with updating my v-if and v-else statements on the frontend, despite having another function in place to check the array length. As a result, I switched to trying to splice the array, but I'm facing difficulties as it keeps returning undefined. Since each element in the array is an object, I suspect that my issue lies in the way I am attempting to access the value, but I am unsure of the correct approach.

The HTML section:

<div class="form-group">

      <input type="text" id='task-entry' class='px-2' @keyup.enter="addTask">
      <a href="#" class='btn btn-info' id='task-button' @click="addTask">Add Task</a>

    </div> <!-- form-group -->

    <hr class='hr my-5 bg-dark'>

    <div class="task-list py-3 bg-white mx-auto w-75">

      <ul v-if='taskList.length > 0' class='mb-0 px-2'>

        <li v-for="tasks in taskList" class='text-dark p-3 task-item text-left clearfix'>
          <div class='task-name float-left'>
              <span>{{ tasks.task }}</span>
          </div>

          <a href="#" class="btn btn-danger remove-task float-right" @click='removeTask'>Remove Task</a>

        </li>

      </ul>

      <div v-else>
        You currently have no tasks.
      </div>

JavaScript code snippet:

new Vue({
  el: '#app',
  data: {
    title: 'To Do List',
    taskList: [],
    showError: false
  },
  methods: {
    addTask: function () {

      var task = document.getElementById('task-entry');

      if (task.value !== '' && task.value !== ' ') {
        this.error(1);
        this.taskList.push({
          task: task.value
        });
        task.value = '';
      } else {
        this.error(0);
      }
    },
    removeTask: function (e) {
      if(e.target.classList.contains('remove-task')) {

        var targetElement = e.target.parentElement;

        var test = targetElement.querySelector('span').innerText;

        console.log(test);
        console.log(this.taskList[{task: test}]);

      } else {
        e.preventDefault;
      }
    },
    error: function (value) {
      if (value === 0) {
        this.showError = true;
      } else {
        this.showError = false;
      }
    }
  }
});

Answer №1

Give this a try: (I've implemented the remove function using VueJS, it's pretty straightforward)

new Vue({
  el: '#app',
  data: {
    title: 'To Do List',
    taskList: [],
    showError: false
  },
  methods: {
    addTask: function() {
      var task = document.getElementById('task-entry');
      if (task.value !== '' && task.value !== ' ') {
        this.error(1);
        this.taskList.push({
          task: task.value
        });
        task.value = '';
      } else {
        this.error(0);
      }
    },
    removeTask: function(tasks) {
      this.taskList.splice(this.taskList.indexOf(tasks), 1)
    },
    error: function(value) {
      if (value === 0) {
        this.showError = true;
      } else {
        this.showError = false;
      }
    }
  }
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="fb8d8e9ebbc9d5ced5cacc">[email protected]</a>/dist/vue.js"></script>

<div id="app">
  <div class="form-group">
    <input type="text" id='task-entry' class='px-2' @keyup.enter="addTask">
    <a href="#" class='btn btn-info' id='task-button' @click="addTask">Add Task</a>
  </div>
  <!-- form-group -->
  <hr class='hr my-5 bg-dark'>
  <div class="task-list py-3 bg-white mx-auto w-75">
    <ul v-if='taskList.length > 0' class='mb-0 px-2'>
      <li v-for="tasks in taskList" class='text-dark p-3 task-item text-left clearfix'>
        <div class='task-name float-left'>
          <span>{{ tasks.task }}</span>
        </div>
        <a href="#" class="btn btn-danger remove-task float-right" @click='removeTask(tasks)'>Remove Task</a>
      </li>
    </ul>
    <div v-else>
      You currently have no tasks.
    </div>
  </div>


Here are two simple steps to ensure your code functions properly:

S1: In the template, update the event handler to @click='removeTask(tasks)', like this:

<a href="#" class="btn btn-danger remove-task float-right" @click='removeTask(tasks)'>Remove Task</a>

S2: In the script, modify the remove method as follows:

removeTask: function(tasks) {
   this.taskList.splice(this.taskList.indexOf(tasks), 1)
}

Answer №2

If you're working with Vue, there's a more Vue-centric approach to achieving your goal without needing to manipulate the DOM directly.

Let's focus on the removeTask method for now.

Array.prototype.splice() is used to remove or insert values in an array based on an index. You can access this index using v-for like so:

<li v-for="(tasks, index) in taskList">

Your "remove" link can then utilize this index:

<a @click.prevent="removeTask(index)">

And your method can be implemented as follows:

removeTask (index) {
  this.taskList.splice(index, 1)
}

When adding tasks, I suggest using v-model to bind the new task to your input field, like this:

<input type="text" v-model="newTask" @keyup.enter="addTask">

Then adjust your data object and methods accordingly:

data: {
  title: 'To Do List',
  taskList: [],
  showError: false,
  newTask: '' // added this
},
methods: {
  addTask () {
    if (this.newTask.trim().length > 0) {
      this.error(1)
      this.taskList.push({ task: this.newTask })
      this.newTask = ''
    } else {
      this.error(0)
    }
  }
}

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

Create a custom Angular directive that allows you to replace tags while inserting the template

I have created a custom directive that can take templates based on the attribute provided. Check out the Plnkr example JS var app = angular.module('app', []); app.directive('sample', function($compile){ var template1 = '<d ...

Fetching data using ajax and then appending it to the webpage

I am currently loading content from a PHP file in JSON format. products.php <?php $stmt = $mysqli->prepare("SELECT * FROM products LIMIT 10"); $stmt->execute(); $products = $stmt->get_result(); $produc ...

Ways to identify if the text entered in a text area is right-to-left justified

Within a textarea, users can input text in English (or any other left-to-right language) or in a right-to-left language. If the user types in a right-to-left language, they must press Right-shift + ctrl to align the text to the right. However, on modern O ...

Tips for aligning the camera to ensure the object maintains a consistent pixel width and height on the screen

I am grappling with a challenge that I'm unsure how to approach, hoping someone can offer me a clue on the solution. My goal is to position the camera at a specific z index so that a cube appears on the screen with consistent pixel dimensions regardl ...

Utilizing Ramda JS for multi-dimensional grouping

I've been attempting to group the object by tag, folder, and report keys using GroupBy at multiple levels. While I was successful in grouping at a single level, I encountered difficulty in progressing further. const data = [{ "_index": "search_in ...

Implement a code to apply to an image that is loaded dynamically

I have a situation on a page where an image is loaded via ajax within a wrapping div. I need to execute some code as soon as that image is loaded. Unfortunately, I am unable to modify the ajax call, which means using on('success') directly on the ...

Display temporary image until real image loads within ng-repeat angularjs

I am looking to display a placeholder image while the actual image is being loaded. I have tried using the ng-image-appear plugin. The issue I'm facing is that the placeholder image does not appear for img elements inside ng-repeat, although it works ...

Working with JSON objects and arrays in Scala Play

I'm attempting to make a third party API call using Play WS in order to retrieve a JSON object containing a collection of objects. My goal is to loop through this collection and append a key/value pair to each item. As someone who is new to Scala and ...

Socket.io in Express is already assigned to another address

I'm having trouble getting my app to connect with Socket.io via websockets. Each time I attempt to run this code snippet, I encounter the following error: Error: listen EADDRINUSE: address already in use :::3000 Despite checking for any other process ...

Storing the current date() in JSON format using AngularJS

I am currently working on saving various data, including the current date, in a JSON file stored in LocalStorage. While I have been successful in saving the data, the date is saved in the ISO 8601 format: [{"date":"2014-10-13T17:55:32.953Z"}] This format ...

Just a Quick Query About Regular Expressions

I need help removing a specific part from a URL string, which looks like this: http://.....?page=1. I am aware that the code "document.URL.replace("?page=[0-9]", "")" does not work, so I am curious to learn how to accomplish this task correctly. Thank you ...

Exploring Specific Locations with AmCharts 5 Zoom Feature

Just starting to use AmCharts 5 and I'm struggling to trigger a simple zoom into a location on a map. No matter which tutorial I follow, I can't seem to replicate the results others are getting. If you want to take a look at my Codepen setup to ...

Code in JavaScript using VueJS to determine if an array includes an object with a certain value in one of its elements

I have a scenario where I need to address the following issue: I have an Object with a property called specs. This property consists of an Array that contains several other Objects, each having two properties: name value Here is an example of what my o ...

Is there a way to capture all ajax responses?

Is it possible to capture all responses from an ajax request, regardless of the library being used such as jQuery, prototype, or just the vanilla XMLHttpRequest object? I am looking for a way to append to any existing handler without removing it. Thank y ...

Tips for creating a mirrored iframe without the need to load the URL twice: CSS does not trigger the desired effect

I have a unique requirement for two iframes - I want only the first iframe to load a specific URL. Once the first iframe finishes loading, I need the second iframe to display the same content without actually loading the URL again. Here is the approach I h ...

How can we stop the anchor jump caused by a third-party script?

I'm currently utilizing a third-party script (details provided below) to divide a form into multiple ajax'd pages. However, when I attempt to move on to the next page, it immediately jumps to an anchor at the top of the form. This behavior is unn ...

The number counter feature in jQuery does not support the use of commas

I'm currently working on a counter that goes from 0 to a specific value, but I'm running into some issues with rendering numbers when they have commas. I've tried using toLocaleString as a potential solution, but I haven't been able to ...

Include a "remember me" feature in the Stripe form

I am currently working on an exciting project using Angular 6. Within my website, I have decided to integrate the Stripe payment system. However, I would like to incorporate a unique and default "remember me" feature offered by Stripe. <div id="card-e ...

How to simulate loadStripe behavior with Cypress stub?

I am struggling to correctly stub out Stripe from my tests CartCheckoutButton.ts import React from 'react' import { loadStripe } from '@stripe/stripe-js' import useCart from '~/state/CartContext' import styles from '. ...

Is there a way to display a message in a div container instead of using the alert box when there is a successful ajax response?

Hey there, I'm currently working on implementing error validation handling for a custom form that I've created. I'm looking to display the error messages in a designated div rather than using the standard browser alert box. Since I'm fa ...