4

I am trying to add an edit function to a task app with Vue JS.

  1. I have a click event on the edit button - @click="editShow" which shows the input for editing for all items. I need this to only show the corresponding input.
  2. Then I cannot get the edit value to save to the items description - @keyup.enter="editTask". For some reason the task refers to the keyup event and not the object. I think that's what is causing the problem.

Here is what I have so far, 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);
        }
    }

})

1 Answer 1

6

I added a editing boolean to your tasks. You can toggle that to swap the individual tasks to edit mode. Additionally, I pass the task through your editTask on the keyup.enter. Finally, since using v-model on your input, there's no saving that needs to be done because the description is two-way bound. Your enter keyup handler just needs to toggle the mode back.

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>

Sign up to request clarification or add additional context in comments.

5 Comments

@ClintonGreen no problem :) There are other ways it could work, but that's the first that came to mind. There's some cleanup that needs to be done. When you add a new task, should set the editing value for example.
Yeah thanks easy as to do, you've done all the heavy lifting. Cheers
@Bert it doesn't seem like the example quite works as expected. When I tried adding an item in the fiddle, then try to edit said item, the editor doesn't open.
@user1477388 You're right, there is a bug. It's here: this.tasklist.push({description: this.newTaskName, completed: false,}); When the fiddle is adding a new item it does not have an editing property. Adding the editing property and defaulting it to false, corrects that bug. The correct code is in the answer, but not in the fiddle.
@Bert Nice! Thanks for updating it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.