How to toggle a property boolean value using a click event method in Vue.js?

I have this array of objects:

const TodosStore = [
  {
    userId: 1,
    id: 1,
    title: "delectus aut autem",
    completed: false,
  },
  {
    userId: 1,
    id: 2,
    title: "quis ut nam facilis et officia qui",
    completed: false,
  },
  {
    userId: 1,
    id: 3,
    title: "fugiat veniam minus",
    completed: false,
  },
  {
    userId: 1,
    id: 4,
    title: "et porro tempora",
    completed: true,
  },
  {
    userId: 1,
    id: 5,
    title: "laboriosam mollitia et enim quasi adipisci quia provident illum",
    completed: false,
  },
];

Which I have imported in a TodoList.vue component like so:

<script>
import TodosStore from "../store/TodosStore";

export default {
  name: "TodoList",
  ...
};
</script>

I wanted to toggle the current todo.completed property boolean with a click event on an input radio HTML element. I was able to do it directly inline like so:

<template>
  <div>
    <h1>Todos:</h1>
    <ul class="todo-list">
      <li
        :class="{ isCompleted: todo.completed }"
        v-for="todo in todos"
        :key="todo.id"
      >
        {{ todo.title }}
        <input
          type="radio"
          :checked="todo.completed"
          @click="todo.completed = !todo.completed"
        />
      </li>
    </ul>
  </div>
</template>

However, I would like to toggle it from a method instead so it scales better. I have tried creating a toggleTodo method with a param, but I can’t figure it out. It seems the array of object is not reactive, I wish to avoid creating a new data property just toggle the boolean value from the original array.

<template>
  <div>
    <h1>Todos:</h1>
    <ul class="todo-list">
      <li
        :class="{ isCompleted: todo.completed }"
        v-for="todo in todos"
        :key="todo.id"
      >
        {{ todo.title }}
        <input
          type="radio"
          :checked="todo.completed"
          @click="toggleTodo(todo.completed)"
        />
      </li>
    </ul>
  </div>
</template>

<script>
import TodosStore from "../store/TodosStore";

export default {
  name: "TodoList",
  data() {
    return {
      todos: TodosStore,
      isCompleted: null,
      // I want to avoid creating a isDone property here to change the current todo.completed property
    };
  },
  methods: {
    toggleTodo(value) {
      return (value = !value)
    },
  },
};
</script>

Thanks in advance!

Hi Manuel, you could probably do it by passing the todo item to the method, rather than the completed prop, e.g.:

...
@click="toggleTodo(todo)"
...

toggleTodo(item) {
      item.completed = !item.completed
}

Just to flag up (please ignore if you already know), it might be worth changing from radio buttons to checkboxes. Radio button are usually used when only one option in a list can be selected, whereas checkboxes are used when multiple selections can be made :+1:

1 Like

@daniel-bolton thanks, it works like a charm!

@Manuel-Suarez-Abasca, no problem :slight_smile:

1 Like