Vue

by Hugo Carneiro

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.24.3/vuedraggable.umd.js"></script>
<div id="app">
  <h2>To do: ({{ todos.length }})</h2>
  <input type="text" placeholder="Type something and press return" ref="input" v-model="todoInput" v-on:keyup.enter="addNewItem"/>
  <ol>
    <draggable :list="todos" group="tasks">
      <li v-for="(item, index) in todos" :key="item.text">
        <label>
          <input type="checkbox" v-model="completedItems" :value="item"/>
          <span>{{ item.text }}</span>
          <a href="#" class="remove" @click="removeItem(index)">Remove</a>
        </label>
      </li>
    </draggable>
  </ol>
  <hr />
  <h2>
  Completed items: ({{ completedItems.length }})
  </h2>
  <ol>
    <draggable :list="completedItems" group="tasks">
      <li v-for="(item, index) in completedItems" :key="item.text">
        <label>
          <span>{{ item.text }}</span>
        </label>
      </li>
    </draggable>
  </ol>
</div>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

del {
  color: rgba(0, 0, 0, 0.3);
}

input[type="text"] {
  padding: 10px;
  width: 200px;
}

label .remove {
  display: none;
  color: red;
}

label:hover .remove {
    display: inline-block;
    margin-left: 10px;
    color: red;
    opacity: 0.5;
}

Vue

new Vue({
  el: "#app",
  data: {
  	todoInput: '',
    todos: [
      { text: "Learn about Vue" },
      { text: "Learn about Fliplet" },
      { text: "Play around in JSFiddle" },
      { text: "Show us what you've got" }
    ],
    completedItems: []
  },
  watch: {
  	completedItems(selectedItems) {
    	this.moveToCompleted(selectedItems)
    }
  },
  methods: {
  	cleanInput() {
    	// Set the input value to empty string
    	this.todoInput = ''
      
      // Focus on the input field to enter a new item
      this.$refs.input.focus()
    },
    moveToCompleted(selectedItems) {
    	// Checks difference between arrays and removes duplicates
    	this.todos = _.differenceWith(this.todos, selectedItems)
    },
  	addNewItem() {
    	// Pushes new item to the bottom of the todo list
    	this.todos.push({
      	text: this.todoInput
      })
      
      // Clean input
      this.cleanInput()
    },
    removeItem(index) {
    	this.todos.splice(index, 1);
    }
  }
})