Building a simple todo app with Vue.js
Over the last few weeks, I’ve started to learn Vue.js, a progressive JavaScript framework. Alongside working through the Frontend Masters course, I decided to try and rebuild my very basic todo app functionality with it.
My app (Today) is a simple todo app - often a go-to build when starting to learn a new language. I'd started to build it using vanilla JavaScript and Electron. Whilst getting my head around Vue I realised that my core functionality needs would be suited to using Vue for, also some of my JavaScript had started to get a little unwieldy!
Today has 4 main actions:
- Display todos
- Add a new todo
- Complete a todo
- Delete a todo
This post will detail how I went about using Vue to achieve each of these.
Note permalink
This post will not go into, or apply any styling to the todo list, or detail any of the Electron implementation (I'll cover those in a further, more in-depth post once it's all good to go).
Here's the finished Codepen of what I built (see the note above about styling etc)
See the Pen Today (Vue functionality concept) by James Bateson (@jim-bateson) on CodePen.
Creating the Vue Instance permalink
The first thing we need to do is attach Vue to a DOM node
new Vue({
el: '.js-todo-app'
});
Displaying the todos permalink
For this demo, I've used some dummy data, when I integrate this with my Electron codebase, I'll need to read and write from a JSON file.
Vue reads all data from its data
object. So in here, we define our todos array
data: {
todos: [
{
title: 'Test todo',
completed: false
},
{
title: 'Test todo 2',
completed: false
}
]
},
To loop through this data and display it, we need to to use v-for
<li v-for="(todo, index) in todos">
{{ todo.title }}
</li>
Here todos
is the array we are looping through and todo
is our name for the array element we are iterating over. You can also pass an (optional) second option to v-for
, which is the index of the item.
Add a new todo permalink
This is where my Vue implementation slightly deviates from the initial vanilla/Electron setup I have. In which Electron creates a new window (view) in which you add a new todo, which is then sent to the main window. However, using Vue things can be made much simpler and handled by the framework.
Firstly let's create an input to enter the new todo (make sure to add an associated label for the input)
<label for="add_todo">Add a new todo</label>
<input type="text" id="add_todo" v-model="newTodo" @keyup.enter="addTodo" name="add_todo" placeholder="Today I want to...">
There are a couple of Vue bits we are attaching to this input:
v-model
is a two way binding on elements such asinput
andtextarea
. Depending on the element, it detects the value/status and passes this data to/from Vue. More info here.@keyup.enter
(can also be writtenv-bind:enter
) this is an example of a Vue event handler, in this instance pressing theenter
key. When this is done, ourAddTodo
method will be run. Pushing the new todo to the todo array (we defined indata
).
Completing a todo permalink
To enable us to complete a todo, there are a couple of things we'll need to setup.
Firstly let's add the element we'll use to action the complete. In this case that's going to be a checkbox.
<label>
<input type="checkbox" v-model="todo.completed">
<span>Make a brew</span>
</label>
Here we are setting the v-model
to the completed property from our data, this means on checking/unchecking the input set that to true/false.
In anticipation of adding some styling to these completed items, we will then make use of Vue's class bindings on the todo item itself.
<li class="todo-item js-todo-item" :class="{ 'todo-item--completed' : todo.completed }">...</li>
We already have a couple of classes on the <li>
this might be for some styling and/or custom JavaScript functionality (they're not important for this demo). Vue allows us to conditionally bind classes (and styles) based on certain conditions being met. Here we're using a ternary to add the todo-item--completed
class if the todo has been completed (based on the value of our model).
Deleting a todo permalink
Once a todo has been completed, or if one is added by mistake, it may need to be deleted. To do this we need to remove it from the data (array).
As of v2.2.0 Vue has a handy delete method built-in.
First let's create a button that will trigger this.
<button @click="deleteTodo(index)">Delete todo</button>
Then create a method in our instance.
deleteTodo(index) {
this.$delete(this.todos, index);
}
We start by passing index as an argument of the method (as defined in our event in the HTML), then use Vue delete. The first argument being the array we are removing the item from and the second using the index we passed into our method.
Todo or not todo? permalink
So we now have our 4 main, core pieces of functionality needed to build a simple todo app! It's a great intro to Vue, using many of the core principles available in the framework.
I'll be expanding on this write up when I finish the app and integrate with Electron and get the app packaged up. But here we have a great start to take a todo list in any direction you wish. It could even be implemented into an existing codebase as I have done - which is one of the great things about Vue!
There are a couple of bits of functionality I'd like to add at some point:
- Don't let a user add duplicate todos
- Sorting options (priority etc)
- Warnings for stale todos
- Categorising todos
- Editing a todo (inline)
Hey! I also made this permalink
As well as going through the Frontend Masters course (linked in the intro), I've found the Vue docs site to be very clear, with some great practical examples. I also made this summary pen of directives and bindings to help me remember things.
See the Pen Directives & Data Rendering by James Bateson (@jim-bateson) on CodePen.