Reputation: 81
I am trying to better myself at JavaScript OOP, and I'm learning vue.js as well. I am building a simple task list to teach myself, and I have most of it done except for the remove task function. I originally was just using the .remove() option, but it was not updating my v-if and v-else statement on my front end, even with another function checking the length of the array. So, I decided to try and splice my array, but I'm a bit lost since it's returning undefined. As each element in the array is an object, I'm sure it's the way I'm trying to call the value, but I'm not too sure how to do so.
Here is the HTML:
<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>
And here is the JavaScript:
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;
}
}
}
});
Upvotes: 3
Views: 6022
Reputation: 10179
Try this: (I implement the remove function in VueJS way, it's really simple)
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/[email protected]/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>
There are two small steps to make your code work as expected:
S1: In the template change 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, re-write the remove method like so:
removeTask: function(tasks) {
this.taskList.splice(this.taskList.indexOf(tasks), 1)
}
Upvotes: 2
Reputation: 164812
There's a much more Vue-specific way to go about what you're trying to achieve and you definitely don't need to be querying the DOM for values.
Let's start with your removeTask
method.
Array.prototype.splice()
uses an index to remove / insert values from an array. You can get this index from v-for
using something like
<li v-for="(tasks, index) in taskList">
Now your remove link can use this index
<a @click.prevent="removeTask(index)">
and your method can use
removeTask (index) {
this.taskList.splice(index, 1)
}
For adding tasks, I recommend using v-model
to bind the new task to your input, eg
<input type="text" v-model="newTask" @keyup.enter="addTask">
and
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)
}
}
}
Upvotes: 1