Day 76 of 100 Days Of Code
Day 76: October 08, Monday
Today ‘s Progress: Great progress on my VUE.js todo app its working!!!!!! Vue.js Todo App - Basics - Part 1and VUE.JS - SIMPLE TODO APP - PART 1 working in a local dev environment. Upgraded to VUE 3.0, Working at last!!!!!
Thoughts: I added my first todo list hereVueApp to a local Git file and use Vue-CLI 3.0 after going though more videos I am finally starting to get it, cautiously optimistic. Debugging continues.
Resources used:
- Github repo for todoApp
- INTERMEDIATE: Learn Vue 2: Step By Step
- Vue.js.org
- VUE.JS - SIMPLE TODO APP - PART 1
It works… more refactoring and debugging tomorrow. PROGRESS!!!!
<template>
<div>
<input type="text" class="todo-input" placeholder="What needs to be done" v-model="newTodo" @keyup.enter="addTodo">
<transition-group name="fade" enter-active-class="animated fadeInUp" leave-active-class="animated fadeOutDown">
<div v-for="(todo, index) in todosFiltered" :key="todo.id" class="todo-item">
<div class="todo-item-left">
<input type="checkbox" v-model="todo.completed">
<div v-if="!todo.editing" @dblclick="editTodo(todo)" class="todo-item-label" :class="{ completed : todo.completed }"></div>
<input v-else class="todo-item-edit" type="text" v-model="todo.title" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)" v-focus>
</div>
<div class="remove-item" @click="removeTodo(index)">
×
</div>
</div>
</transition-group>
<div class="extra-container">
<div><label><input type="checkbox" :checked="!anyRemaining" @change="checkAllTodos"> Check All</label></div>
<div> items left</div>
</div>
<div class="extra-container">
<div>
<button :class="{ active: filter == 'all' }" @click="filter = 'all'">All</button>
<button :class="{ active: filter == 'active' }" @click="filter = 'active'">Active</button>
<button :class="{ active: filter == 'completed' }" @click="filter = 'completed'">Completed</button>
</div>
<div>
<transition name="fade">
<button v-if="showClearCompletedButton" @click="clearCompleted">Clear Completed</button>
</transition>
</div>
</div>
</div>
</template>
<script>
/* eslint-disable */
export default {
name: 'todo-list',
data () {
return {
newTodo: '',
idForTodo: 3,
beforeEditCache: '',
filter: 'all',
todos: [
{
'id': 1,
'title': 'Finish Vue Screencast',
'completed': false,
'editing': false,
},
{
'id': 2,
'title': 'Take over world',
'completed': false,
'editing': false,
},
]
}
},
computed: {
remaining() {
return this.todos.filter(todo => !todo.completed).length
},
anyRemaining() {
return this.remaining != 0
},
todosFiltered() {
if (this.filter == 'all') {
return this.todos
} else if (this.filter == 'active') {
return this.todos.filter(todo => !todo.completed)
} else if (this.filter == 'completed') {
return this.todos.filter(todo => todo.completed)
}
return this.todos
},
showClearCompletedButton() {
return this.todos.filter(todo => todo.completed).length > 0
}
},
directives: {
focus: {
inserted: function (el) {
el.focus()
}
}
},
methods: {
addTodo() {
if (this.newTodo.trim().length == 0) {
return
}
this.todos.push({
id: this.idForTodo,
title: this.newTodo,
completed: false,
editing: false,
})
this.newTodo = ''
this.idForTodo++
},
editTodo(todo) {
this.beforeEditCache = todo.title
todo.editing = true
},
doneEdit(todo) {
if (todo.title.trim() == '') {
todo.title = this.beforeEditCache
}
todo.editing = false
},
cancelEdit(todo) {
todo.title = this.beforeEditCache
todo.editing = false
},
removeTodo(index) {
this.todos.splice(index, 1)
},
checkAllTodos() {
this.todos.forEach((todo) => todo.completed = event.target.checked)
},
clearCompleted() {
this.todos = this.todos.filter(todo => !todo.completed)
}
}
}
</script>
<style lang="scss">
@import url("https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css");
.todo-input {
font-family: "Comic Sans MS", cursive, sans-serif;
width: 100%;
padding: 10px 18px;
font-size: 18px;
margin-bottom: 16px;
&:focus {
outline: 0;
}
}
.todo-item {
font-family: "Comic Sans MS", cursive, sans-serif;
margin-bottom: 12px;
display: flex;
align-items: center;
justify-content: space-between;
animation-duration: 0.3s;
}
.remove-item {
cursor: pointer;
margin-left: 14px;
&:hover {
color: black;
}
}
.todo-item-left { // later
display: flex;
align-items: center;
}
.todo-item-label {
padding: 10px;
border: 1px solid white;
margin-left: 12px;
}
.todo-item-edit {
font-size: 24px;
color: #2c3e50;
margin-left: 12px;
width: 100%;
padding: 10px;
border: 1px solid #ccc; //override defaults
font-family: 'Avenir', Helvetica, Arial, sans-serif;
&:focus {
outline: none;
}
}
.completed {
text-decoration: line-through;
color: grey;
}
.extra-container {
font-family: "Comic Sans MS", cursive, sans-serif;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 16px;
border-top: 1px solid lightgrey;
padding-top: 14px;
margin-bottom: 14px;
}
button {
font-family: "Comic Sans MS", cursive, sans-serif;
padding: 5px 35px;
font-size: 14px;
background-color: white;
appearance: none;
&:hover {
background: lightblue;
}
&:focus {
outline: none;
}
}
.active {
background: lightblue;
}
// CSS Transitions
.fade-enter-active, .fade-leave-active {
transition: opacity .2s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
Link(s) to work
- Working on my TODO application in local environment.
Code is at https://github.com/Johnny2136/my-todo-app.
Written on October 8, 2018