skip to Main Content

I’m expecting clicking the Done/Undone individual task button to toggle the task data completed to opposite using Vuex store actions. But I’m getting the 404 error. Even though I’m passing the task id from the child component. Or should I do it with mutations?

https://stackblitz.com/edit/nuxt-bootstrap-vue-dynamic-img-bkwixg?file=store%2Findex.js,components%2FTask.vue

// Child component

<template>
  <div :class="{ task: task.completed }">
    <p class="content">
      {{ task.todo }}
    </p>
      <button @click="toggleTask">
        {{ task.completed ? 'Undone' : 'Done' }}
      </button>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  props: ['task'],
  methods: {
    toggleTask(id) {
      this.$store.dispatch('toggleTask', id);
    },
  },
};
</script>

// Parent component

<template>
      <Task v-for="task in tasks" :key="task.id" :task="task" />
</template>

<script>
export default {
  data() {
    return {
      todo: '',
      completed: false,
      search: '',
    };
  },
  computed: {
    tasks() {
      return this.$store.getters.getTasks(this.search);
    },
  },
  mounted() {
    this.$store.dispatch('getTasks').then((data) => console.log(this.tasks));
  },
};
</script>

// Store 

export const state = () => ({
  tasks: [],
});

export const actions = {
  async getTasks(context) {
    const res = await fetch('https://dummyjson.com/todos/user/5');
    if (res.ok) {
      let result = await res.json();
      context.commit('setTasks', result.todos);
    }
    return res.ok;
  },
  async toggleTask(context, id) {
    const res = await fetch(`https://dummyjson.com/todos/${id}`, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
      },
      // body: JSON.stringify(data),
    });
    if (res.ok) {
      const tasks = (context.state.tasks.find(
        (task) => task.id === id
      ).completed = !completed);
      context.commit('setTask', id);  // or should I commit to toggle task mutation and how can I do it ?
    }
    return res.ok;
  },
};

export const mutations = {
  setTasks(state, data) {
    state.tasks = data;
  },
  toggleTask(state, id) {
    state.tasks.find((task) => task.id === id).completed = !completed;
  },
};

export const getters = {
  },
};

2

Answers


  1. In the click handler

     toggleTask(id) {
      this.$store.dispatch('toggleTask', id);
     },
    

    id is an event object. You need to properly pass the id here. Below should work

    this.$store.dispatch('toggleTask', this.task.id);
    
    Login or Signup to reply.
  2. First, You pass task to method:

    <button @click="toggleTask(task)">
      {{ task.completed ? 'Undone' : 'Done' }}
    </button>
    

    then in Vuex create action that will put data and commit mutation:

    async toggleTask(context, task) {
      const res = await fetch(`https://dummyjson.com/todos/${task.id}`, {
        method: 'PUT',
        headers: {
          'Content-Type': 'application/json;charset=utf-8',
        },
        body: JSON.stringify({completed: !task.completed}),
      })
      let result = await res.json();
      context.commit('updateTask', result)
    },
    

    at the end mutation:

    updateTask(state, task) {
      state.tasks = [
        ...state.tasks.map(item => 
          item.id !== task.id ? item : {...item, ...task}
        )
      ] 
    },
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search