pawel szewczyk
pawel szewczyk

Reputation: 261

Vue.js checkbox bound via v-model to false value is checked

I am trying to make a todo list with like Eisenhower matrix, and i have a problem because v-bind and v-model is triggered on a false

How can i fix this bug ?enter image description here Code is inspired by Vue.js Todo App - Basics - Part 1

 <div class="todoList" v-for="(task, index) in todo" :key="task.id">
                    <div>
                        <div v-if="task.type == 'notimportant'">
                            <input v-model="task.completed" type="checkbox" name="" id="" @change="completeTask(task)" />
                            <div class="task" v-bind:class="{ completed: task.completed }">
                                {{ task.title }}
                            </div>
                            <button class="removeTask" @click="removeTask(index)">X</button>
                        </div>
                    </div>
                </div>
export default {
    name: "app",
    data() {
        return {
            newTodo: "",
            type: "",
            important: "",
            id: 3,
            todo: [
                {
                    id: 1,
                    title: "Fist Task",
                    completed: "false",
                    editing: "false",
                    type: "urgent",
                },
                {
                    id: 2,
                    title: "Second Task",
                    completed: "false",
                    editing: "false",
                    type: "important",
                },
            ],
        };
    },

full code

<template>
    <div id="app">
        <div class="conteiner">
            <input placeholder="what we do ?" type="text" v-model="newTodo" />
            <button @click="addTask()">Add</button>
            <select v-model="type">
                <option disabled value="">Select</option>
                <option value="urgent">Urgent</option>
                <option value="noturgent">Not Urgent</option>
                <option value="important">Important</option>
                <option value="notimportant">Not Important</option>
            </select>
            <div class="todoBox">
                <h2>Urgent</h2>
                <div class="todoList" v-for="(task, index) in todo">
                    <div>
                        <div v-if="task.type == 'urgent'">
                            <input v-model="task.completed" type="checkbox" name="" id="" @change="completeTask(task)" />
                            <div class="task" v-bind:class="{ completed: task.completed }">
                                {{ task.title }}
                            </div>
                            <button class="removeTask" @click="removeTask(index)">X</button>
                        </div>
                    </div>
                </div>
            </div>
            <div class="todoBox">
                <h2>Not Urgent</h2>
                <div class="todoList" v-for="(task, index) in todo" :key="task.id">
                    <div>
                        <div v-if="task.type == 'noturgent'">
                            <input v-model="task.completed" type="checkbox" name="" id="" @change="completeTask(task)" />
                            <div class="task" v-bind:class="{ completed: task.completed }">
                                {{ task.title }}
                            </div>
                            <button class="removeTask" @click="removeTask(index)">X</button>
                        </div>
                    </div>
                </div>
            </div>

            <div class="todoBox">
                <h2>Important</h2>
                <div class="todoList" v-for="(task, index) in todo" :key="task.id">
                    <div>
                        <div v-if="task.type == 'important'">
                            <input v-model="task.completed" type="checkbox" name="" id="" @change="completeTask(task)" />
                            <div class="task" v-bind:class="{ completed: task.completed }">
                                {{ task.title }}
                            </div>
                            <button class="removeTask" @click="removeTask(index)">X</button>
                        </div>
                    </div>
                </div>
            </div>
            <div class="todoBox">
                <h2>Not Important</h2>
                <div class="todoList" v-for="(task, index) in todo" :key="task.id">
                    <div>
                        <div v-if="task.type == 'notimportant'">
                            <input v-model="task.completed" type="checkbox" name="" id="" @change="completeTask(task)" />
                            <div class="task" v-bind:class="{ completed: task.completed }">
                                {{ task.title }}
                            </div>
                            <button class="removeTask" @click="removeTask(index)">X</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: "app",
    data() {
        return {
            newTodo: "",
            type: "",
            important: "",
            id: 3,
            todo: [
                {
                    id: 1,
                    title: "Fist Task",
                    completed: "false",
                    editing: "false",
                    type: "urgent",
                },
                {
                    id: 2,
                    title: "Second Task",
                    completed: "false",
                    editing: "false",
                    type: "important",
                },
            ],
        };
    },
    methods: {
        addTask() {
            if (this.newTodo.trim().length == 0) {
                return;
            }
            this.todo.push({
                id: this.id,
                title: this.newTodo,
                completed: "false",
                editing: "false",
                type: this.type,
            });
            this.id++;
            this.newTodo = "";
        },
        removeTask(index) {
            this.todo.splice(index, 1);
        },
        completeTask(task) {
            task.completed = event.target.checked;
        },
    },
    directives: {
        focus: {
            inserted: function (el) {
                el.focus();
            },
        },
    },
};
</script>

<style>
* {
    margin: 0px;
    box-sizing: border-box;
}
.removeTask {
}
.completed {
    text-decoration: line-through;
}
.task {
    text-decoration: 0;
}

/*
.conteiner {
    display: flex;
} /*
.todoBox {
    width: 50%;
    height: 50vh;
    border: 1px solid black;
    text-align: center;
}
.todoList {
    width: 100%;
    height: 100%;
    border: 1px solid red;
}
*/
</style>

Upvotes: 0

Views: 340

Answers (1)

Boussadjra Brahim
Boussadjra Brahim

Reputation: 1

The issue is that you're writing false as string such "false" which is evaluated to true, you should know that empty string '', 0 value, null and undefined are evaluated as false and vice-versa

learn more about type coercion here

let app = new Vue({
  el: "#app",
  data() {
    return {
      newTodo: "",
      type: "",
      important: "",
      id: 3,
      todo: [{
          id: 1,
          title: "Fist Task",
          completed: false,
          editing: "false",
          type: "urgent",
        },
        {
          id: 2,
          title: "Second Task",
          completed: false,
          editing: "false",
          type: "important",
        },
      ],
    };
  },
  methods: {
    addTask() {
      if (this.newTodo.trim().length == 0) {
        return;
      }
      this.todo.push({
        id: this.id,
        title: this.newTodo,
        completed: "false",
        editing: "false",
        type: this.type,
      });
      this.id++;
      this.newTodo = "";
    },
    removeTask(index) {
      this.todo.splice(index, 1);
    },
    completeTask(task) {
      task.completed = event.target.checked;
    },
  },
  directives: {
    focus: {
      inserted: function(el) {
        el.focus();
      },
    },
  },
})
* {
  margin: 0px;
  box-sizing: border-box;
}

.removeTask {}

.completed {
  text-decoration: line-through;
}

.task {
  text-decoration: 0;
}


/*
.conteiner {
    display: flex;
} /*
.todoBox {
    width: 50%;
    height: 50vh;
    border: 1px solid black;
    text-align: center;
}
.todoList {
    width: 100%;
    height: 100%;
    border: 1px solid red;
}
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div class="conteiner">
    <input placeholder="what we do ?" type="text" v-model="newTodo" />
    <button @click="addTask()">Add</button>
    <select v-model="type">
      <option disabled value="">Select</option>
      <option value="urgent">Urgent</option>
      <option value="noturgent">Not Urgent</option>
      <option value="important">Important</option>
      <option value="notimportant">Not Important</option>
    </select>
    <div class="todoBox">
      <h2>Urgent</h2>
      <div class="todoList" v-for="(task, index) in todo">
        <div>
          <div v-if="task.type == 'urgent'">
            <input v-model="task.completed" type="checkbox" name="" id="" @change="completeTask(task)" />
            <div class="task" v-bind:class="{ completed: task.completed }">
              {{ task.title }}
            </div>
            <button class="removeTask" @click="removeTask(index)">X</button>
          </div>
        </div>
      </div>
    </div>
    <div class="todoBox">
      <h2>Not Urgent</h2>
      <div class="todoList" v-for="(task, index) in todo" :key="task.id">
        <div>
          <div v-if="task.type == 'noturgent'">
            <input v-model="task.completed" type="checkbox" name="" id="" @change="completeTask(task)" />
            <div class="task" v-bind:class="{ completed: task.completed }">
              {{ task.title }}
            </div>
            <button class="removeTask" @click="removeTask(index)">X</button>
          </div>
        </div>
      </div>
    </div>

    <div class="todoBox">
      <h2>Important</h2>
      <div class="todoList" v-for="(task, index) in todo" :key="task.id">
        <div>
          <div v-if="task.type == 'important'">
            <input v-model="task.completed" type="checkbox" name="" id="" @change="completeTask(task)" />
            <div class="task" v-bind:class="{ completed: task.completed }">
              {{ task.title }}
            </div>
            <button class="removeTask" @click="removeTask(index)">X</button>
          </div>
        </div>
      </div>
    </div>
    <div class="todoBox">
      <h2>Not Important</h2>
      <div class="todoList" v-for="(task, index) in todo" :key="task.id">
        <div>
          <div v-if="task.type == 'notimportant'">
            <input v-model="task.completed" type="checkbox" name="" id="" @change="completeTask(task)" />
            <div class="task" v-bind:class="{ completed: task.completed }">
              {{ task.title }}
            </div>
            <button class="removeTask" @click="removeTask(index)">X</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Upvotes: 1

Related Questions