I have a module called todosModule that stores necessary state information. The todos array holds objects, and when I iterate through them in a loop, I want the completed property of a specific object to change when the checkbox state changes.
The completed property is boolean.
Below is the content of the todosModule.js file for Vuex store:
import axios from "axios";
export const todosModule = {
state: () => ({
todos: [],
page: 1,
limit: 10,
totalPages: 0,
isTodosLoading: false
}),
getters: {
},
mutations: {
setTodos(state, todos) {
state.todos = todos;
},
setPage(state, page) {
state.page = page;
},
setTotalPages(state, totalPages) {
state.totalPages = totalPages;
},
setLoadingTodos(state, bool) {
state.isTodosLoading = bool;
},
setCompleted(state, completed) {
console.log(state.todos.completed);
state.todos.completed = completed;
}
},
actions: {
async fetchTodos({state, commit}) {
try {
commit('setLoadingTodos', true);
const response = await axios.get('https://jsonplaceholder.typicode.com/todos', {
params: {
_page: state.page,
_limit: state.limit
}
});
commit('setTotalPages', Math.ceil(response.headers['x-total-count'] / state.limit));
commit('setTodos', response.data);
} catch (e) {
console.log(e);
} finally {
commit('setLoadingTodos', false);
}
}
},
namespaced: true
}
Below is the code for TodoItem.vue:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<div class="col">
<div class="card">
<div class="card-body" :class="todo.completed ? 'bg-light' : ''">
<div class="d-flex align-self-center justify-content-between">
<h5 class="card-title">{{todo.title}}</h5>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="flexSwitchCheckChecked" @change="setCompleted" :checked="todo.completed">
</div>
</div>
<p v-if="todo.completed === true" class="card-text text-success">Completed</p>
<p v-else class="card-text text-danger">Not Completed</p>
<div class="d-flex align-content-center justify-content-between">
<div class="btn-list">
<button-bootstrap css-class="btn-primary">Edit</button-bootstrap>
<button-bootstrap css-class="btn-danger">Delete</button-bootstrap>
</div>
<div class="card-date d-inline-flex text-muted">
<span class="align-self-center">ID: {{todo.id}}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import ButtonBootstrap from "@/components/UI/ButtonBootstrap";
export default {
name: "TodoItem",
components: {ButtonBootstrap},
props: {
todo: {
type: Object,
required: true
}
},
methods: {
setCompleted(event) {
this.$store.commit('todos/setCompleted', event.target.checked);
},
}
}
</script>
<style lang="scss" scoped>
.form-switch .form-check-input {
margin-left: 0;
}
.btn-list {
button:first-child {
margin-right: 1rem;
}
}
</style>
Parent file TodoList.vue:
<template>
<div class="row row-cols-1 g-4">
<TodoItem v-for="todo in todos" :todo="todo" :key="todo.id"/>
</div>
</template>
<script>
import TodoItem from "@/components/TodoItem";
export default {
name: "TodoList",
components: {TodoItem},
props: {
todos: {
type: Array,
required: true,
}
}
}
</script>
<style lang="scss" scoped>
.row {
margin-top: 2rem;
}
</style>
Could someone please help me with changing a specific property of a particular object?
UPDATE! I found a solution!
setCompleted(state, completed) {
const index = state.todos.findIndex(todo => todo.id === completed.id);
state.todos[index].completed = completed.completed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>