Updating item information within an array in Vue.js

I'm currently working on integrating an edit feature into a task application using Vue JS.

  1. My issue lies in the fact that I have a click event assigned to the edit button - @click="editShow" which displays input fields for editing all items instead of just the corresponding one.
  2. Furthermore, I'm struggling with saving the edited value to the description of each item. The keyup event - @keyup.enter="editTask" seems to refer to the keyup event itself rather than the object, causing the problem.

You can view my current progress here: https://jsfiddle.net/clintongreen/0p6bvd4j/

HTML

    <div class="container" id="tasks">

    <div class="panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title">
            {{ message }}
        </h3>
      </div>
      <ul class="list-group">
        <li class="list-group-item clearfix" v-for="task in tasklist" >
            <strong v-if="!editActive">{{ task.description }}</strong>
            <input v-model="editTaskName" v-bind:placeholder="task.description" v-if="editActive" @keyup.enter="editTask" type="text" class="form-control input-height pull-left">
            <div class="btn-group btn-group-sm pull-right" role="group" v-if="!task.completed">
              <button type="button" class="btn btn-default" @click="completeTask(task)">Complete</button>
              <button type="button" @click="editShow" class="btn btn-default">Edit</button>
              <button type="button" class="btn btn-default" @click="removeTask(task)">Remove</button>
            </div>
            <button class="btn btn-default btn-sm completed text-muted pull-right disabled btn-width" v-else>Completed</button>
        </li>
        <li class="list-group-item clearfix">
            <input v-model="newTaskName" @keyup.enter="newTask" type="text" class="form-control input-height pull-left">
            <button class="btn btn-success btn-sm pull-right btn-width" @click="newTask">Add Task</button>
        </li>
      </ul>
    </div>

</div>

JS

    new Vue({

    el: '#tasks',

    data: {
        message: 'Tasks',
        completed: null,
        newTaskName: '',
        editTaskName: '',
        editActive: false,
        tasklist: [
            { description: 'Read', completed: true },
            { description: 'Write', completed: true },
            { description: 'Edit', completed: false },
            { description: 'Publish', completed: false }
        ]
    },

    methods: {
        completeTask: function(task){
            task.completed = true;
        },
        newTask: function(){
            this.tasklist.push({description: this.newTaskName, completed: false});
        },
        removeTask: function(task){
            this.tasklist.splice(this.tasklist.indexOf(task), 1);
            console.log(task);
        },
        editShow: function(task){
            this.editActive = true // should only show the corresponding edit input
            console.log(task);
        },
        editTask: function(task){
            console.log(task);
        }
    }

})

Answer №1

I updated your task list to include an "editing" boolean, allowing you to switch individual tasks into edit mode. I also modified the editTask function to be triggered when the "Enter" key is pressed. With the use of v-model on the input field, there is no need for a separate save function as the description is automatically bound in both directions. Simply pressing Enter toggles back to view mode.

new Vue({

    el: '#tasks',

    data: {
        message: 'Tasks',
        completed: null,
        newTaskName: '',
        tasklist: [
            { description: 'Read', completed: true, editing: false },
            { description: 'Write', completed: true, editing: false  },
            { description: 'Edit', completed: false, editing: false  },
            { description: 'Publish', completed: false, editing: false  }
        ]
    },

    methods: {
        completeTask: function(task){
            task.completed = true;
        },
        newTask: function(){
            this.tasklist.push({description: this.newTaskName, completed: false, editing: false});
        },
        removeTask: function(task){
            this.tasklist.splice(this.tasklist.indexOf(task), 1);
            console.log(task);
        },
        editTask: function(task){
            task.editing = false;
            console.log(task);
        }
    }

})
body{
margin-top: 4em;
}
.completed{
text-decoration: line-through;
}
.btn-width{
width: 182px;
}
.input-height{
width: 346px !important;
height: 30px;
}
.container{
width: 600px;
}
strong{
line-height: 2.2;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div class="container" id="tasks">

    <div class="panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title">
            {{ message }}
        </h3>
      </div>
      <ul class="list-group">
        <li class="list-group-item clearfix" v-for="task in tasklist" >
            <strong v-if="!task.editing">{{ task.description }}</strong>
            <input v-model="task.description" v-if="task.editing" @keyup.enter="editTask(task)" type="text" class="form-control input-height pull-left">
            <div class="btn-group btn-group-sm pull-right" role="group" v-if="!task.completed">
              <button type="button" class="btn btn-default" @click="completeTask(task)">Complete</button>
              <button type="button" @click="task.editing = true" class="btn btn-default">Edit</button>
              <button type="button" class="btn btn-default" @click="removeTask(task)">Remove</button>
            </div>
            <button class="btn btn-default btn-sm completed text-muted pull-right disabled btn-width" v-else>Completed</button>
        </li>
        <li class="list-group-item clearfix">
            <input v-model="newTaskName" @keyup.enter="newTask" type="text" class="form-control input-height pull-left">
            <button class="btn btn-success btn-sm pull-right btn-width" @click="newTask">Add Task</button>
        </li>
      </ul>
    </div>

</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

Tips for using the .innerHTML method to reference multiple indexes

How can I set the .innerHTML for multiple indexes of an array? I currently have an array let poles = Array.prototype.slice.call(document.querySelectorAll(".pole")); This array contains 9 empty divs, such as : <div class="pole" id="1"></div> ...

Generating dynamic div elements using jQuery

I am currently working on developing a button that will automatically generate pre-formatted divs each time it is clicked. The divs consist of forms with fields that should already be populated with data stored in JavaScript variables. Example: <d ...

Error handling in Vuex store action when a promise is returned

I've been working on setting up a login action with Parser for handling authentication errors. However, I'm encountering an issue where I always receive an unhandled promise rejection when trying to catch the error and display it in the component ...

An introduction to integrating Paged.js with Vue.js3

index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> < ...

Supply mandatory argument along with varying arguments to the function

I have a function that requires one parameter and a dynamic set of additional parameters. I am passing an array of blobs to the function. Below is a simplified version of the function: function test(directory, blob0, blob1) { for (var argumentIndex = 1; ...

I am struggling to extract data from the spawned Node.js child process. What am I overlooking?

Trying to utilize a spawned command-line process for lzip in order to expand an lzipped data stream due to the lack of suitable native JavaScript tools. Succeeded in achieving this by working with files and file descriptors, although cumbersome to handle ...

The functionality of cloning in jQuery may encounter an issue where the text field remains enabled if the user selects an option labeled "other

Currently, I am working on a jQuery clone with my existing code and everything is functioning well. In the first scenario, if the user selects other from the dropdown menu, the text field becomes enabled. In the second scenario, when the user clicks ...

When I click on the md-select element, a superfluous "overflow-y: scroll;" gets added to the <body> of my webpage

Typically, I have the following styles on my body: element.style { -webkit-app-region: drag; } However, when I interact with a md-select element (you can observe this behavior on the provided link), additional styles are applied. element.style { -w ...

What causes the issue when attempting to import multiple CSS files in a Vue.js project using @import more than once?

Currently, I am working on a project that involves one main component and several child components. These components require custom CSS files as well as additional vendor CSS files. A challenge I encountered is that I cannot use the @import "path/to/css/fi ...

Utilizing state in React to both store and retrieve data

I'm a newcomer to web development, looking to enhance my React skills by creating a simple weather app using the OpenWeatherMap API. My goal is to store the API response in state to avoid multiple calls. useEffect(() => { let API = " ...

Suggestions for this screenplay

I am completely new to the world of coding and computer languages, and I could use some guidance on how to utilize this script for a flash sale. setInterval(function() { var m = Math.floor((new Date).getTime()/1000); if(m == '1476693000000& ...

Tips on quickly validating a form using JavaScript

I've set up a form with 3 text inputs and a validation function that triggers on submit. Here's a snippet of the code: <form action="" method="post" onSubmit="return checkForm(this.form)"> and checkForm(): var pattern_name = /^([a-zA-Z ...

The MDBDataTable features header sections at both the top and bottom, but the filters UI seems to be

Currently, I am working with MDBDataTable and encountering an issue with the double heading that appears both on top and bottom of the table. I am unsure how to remove it. The code snippet in question is as follows: There is a function that retrieves and ...

Inject a directive attribute dynamically into an element using another directive, and ensure the initial directive is set to 'active.'

Let me explain in more detail. I am utilizing the tooltip directive from the UI Bootstrap suite, which allows me to attach a tooltip to an input element like this: <input type="text" ng-model="inputModel" class="form-control" placeholder=" ...

The Hyperledger Sawtooth JavaScript SDK has encountered invalid submitted batches

I am currently working on integrating a hyperledger sawtooth transaction using the javascript SDK. I am following the tutorial provided here: . /* *Create the transaction header */ const createTransactionHeader = function createTransactionHeader(payloadBy ...

The process of automating e-signature input with Selenium

Is there a way to automate e-signature input in Selenium? I attempted using the action class to draw a line on the canvas object. Below is the code I used: Actions actionBuilder=new Actions(driver); Action drawOnCanvas=actionBuilder ...

Using TypeOrm QueryBuilder to establish multiple relations with a single table

Thank you for taking the time to read and offer your assistance! I am facing a specific issue with my "Offer" entity where it has multiple relations to "User". The code snippet below illustrates these relationships: @ManyToOne(() => User, (user) => ...

Nuxt.js implemented with Auth using jwt refresh tokens

I've implemented the Auth library in my Vue/Nuxt project and have successfully set up JWT Authentication. However, I'm encountering an issue with the refresh token. The refreshToken cookie is consistently being set to null: https://i.sstatic.ne ...

Exploring an ArrayList using a user-defined object

Hey there, I'm currently facing a problem in searching for a specific string within a multi-dimensional ArrayList. I am working on creating a text-based adventure game where players collect various items. Each item is defined with the following proper ...

Learn how to transfer and retrieve data in a different jade template using Node.js without relying on session management or query strings

I am currently facing an issue where I need to redirect and send data from one view to another in a single step using Jade templates. The code snippet below shows my attempt: customer.js var express = require('express'); var router = express.Ro ...