Reputation: 487
I have a todo list that is generated via jsonplaceholder , the button on click populates the div with dummy content.
What I am trying to achieve is that when I click on an individual div(task) it should be removed/hidden.
So far,
<button id="btn" v-on:click= 'getTodo'>Show Todo</button>
<div id="jsonData" v-for = 'todo in todos' >
<ul v-bind:class = '{active: isActive}' v-on:click = 'removeTask'>
<li>{{todo.title}} </li>
<li id="status"> Task Status : {{todo.completed}} </li>
</ul>
</div>
JS
var vm = new Vue({
el: '#app',
data() {
return {
todos: [],
isActive: false
}
},
methods: {
getTodo: function() {
axios.get('https://jsonplaceholder.typicode.com/todos')
.then((response) => {
this.todos = response.data;
})
},
removeTask: function() {
this.isActive = !this.isActive;
}
}
})
The 'removeTask' event handler toggles the classes for all the generated divs(tasks) and not to the clicked div.
How do I add/remove the class on the clicked div?
Upvotes: 0
Views: 1882
Reputation: 1960
Using the axios
API i get the todos and pragmatically loop over the individual todos and apply an isActive
prop to all of them.
These props can now be toggled via toggleTodo
when passing the todo' id
to the method. :-)
Notice i have applied a v-if="todo.isActive"
upon the ul
this can also be translated to :class="{active: todo.isActive}"
if you were wanting to apply some styling i.e for transitions etc.
By using this approach you can use the same logic to create methods such as completeTodo
and removeTodo
etc
I have added a showList
prop in order to show/hide the actual full list.
I noticed you are using v-bind
and v-on
- this is absolutely valid but VUE ^2.0 can handle shorthand binding :-)
I also noticed you are using single
quotes for your HTML attributes... Although this does not break your markup i think it's best practice to keep them as double quotes
.
var vm = new Vue({
el: '#app',
data: {
todos: [],
showList: false
},
mounted () {
this.getTodos()
},
methods: {
getTodos () {
axios.get('https://jsonplaceholder.typicode.com/todos')
.then(res => {
res.data = res.data.map(todo => {
todo.isActive = false
return todo
})
this.todos = res.data
})
},
showTodos () { this.showList = !this.showList },
toggleTodo (id) {
this.todos = this.todos.map(todo => {
if (todo.id === id) {
todo.isActive = !todo.isActive
}
return todo
})
}
}
})
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
<button @click="showTodos()">{{this.showList ? 'Hide' : 'Show'}} Todos</button>
<div v-if="todos.length && showList" v-for="todo in todos">
<button id="btn" @click="toggleTodo(todo.id)">Toggle Todo</button>
<ul v-if="todo.isActive" :class="{active: todo.isActive}">
<li>{{todo.title}} </li>
<li id="status"> Task Status : {{todo.completed}} </li>
</ul>
</div>
</div>
<style lang="css">
.active {
border: 2px solid green;
}
</style>
Upvotes: 3
Reputation: 14992
isActive
is one for the entire instance, not every individual todo.
What you'll need to do is to to populate the todo list either by mapping the response data or simply use the response data's completed
property.
{
"userId": 10,
"id": 193,
"title": "rerum debitis voluptatem qui eveniet tempora distinctio a",
"completed": true
}
Every item of the response's todo has the completed
prop, so you can use that.
That's how you'd go about doing it:
var vm = new Vue({
el: '#app',
data() {
return {
todos: []
}
},
methods: {
getTodo: function() {
axios.get('https://jsonplaceholder.typicode.com/todos')
.then((response) => {
this.todos = response.data;
})
},
toggleCompleted: function(todo) {
todo.completed = !todo.completed;
}
}
})
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<div id="app">
<button id="btn" v-on:click='getTodo'>Show Todo</button>
<div id="jsonData" v-for='todo in todos'>
<ul v-bind:class='{active: todo.completed}' v-on:click='toggleCompleted(todo)'>
<li>{{todo.title}} </li>
<li id="status"> Task Status : {{todo.completed ? 'Completed' : 'Active'}} </li>
</ul>
</div>
</div>
Upvotes: 1