Jump to content

Creating a to-do list with the Vue 3 Composition API.

First off let’s create a typescript interface, describing how our data will be structured. To-do components are pretty simple, we need to know a couple of things: the name of each item and whether it is checked or not. We will also handle the ToDoListItem component props as a separate interface, using the initial interface as a base.

A good reason to start with typings before handling data is so you can have an overview of what is required and plan how you’re going to achieve your goal. We know that we need a name and checked status and we know we need to handle deletion and change (checked) at the item level – so we can cater for that and set up all the relations at the beginning.

Create a new folder and file at src/types/to-do-item.ts – this is where we will write our types for the ToDoListItem. The first interface we will create is ToDoItem, this will describe the name and checked properties and corresponding types: string and boolean respectively.

interface ToDoItem {
    name: string
    checked: boolean

export type {

Don’t forget to export your types!

This interface will be used in the parent ToDoList component to help structure our data and used in the ToDoListItem component to define the props.

Both defineProps and defineEmits use a generic type which allows us to pass the types to the functions in question with this syntax: myFunction(). So we will pass ToDoItem to our definition of props and for our emit definition, we will add another event for delete.

Now with access to our delete event, we can create a function called handleDelete to emit the event with our props.task payload.

With access to our props, we can pass props.checked as the default value to the ref assigned to isChecked.

We will use the @click directive to assign the function we created a moment ago, handleDelete. Clicking the DeleteIcon then will trigger our delete event – just as we wanted! We will also update .item__name content with {{ props.task.name }} – we use the handlebars syntax to bind and display data in the template.

Next up is rendering the list of items based off a bit of mock data for now. So we will have to create a component named ToDoList and render our tasks.

We move our simple

    and elements from App.vue and put it in our new ToDoList component. In our script section we set up our props to receive tasks, and utilise the ref API and pass the tasks prop as our default value.

    Don’t forget to give your ToDoListItem a key relative to your v-for loop – so we can just use task.name + ix here.

    We will require an event handling function for when the ToDoListItem gets checked – we need to find the index of the current task and then set its checked value to be what is passed via the parameters for the event handler.

    As we have tasks setup with the ref API – we can easily update the data via the .value property, selecting our index and then setting the checked property with our boolean! Nice and simple.

    Let’s not forget to change the App.vue to check our new component is working!


    Next up we should add an input to add new tasks and do some general styling updates. We add some basic markup and styling to our new markup.


    The last part we need to do now is hook up an event handler when the user presses the Enter key. Luckily in Vue we can use a “key modifier” – which allows us to check for specific keys. We will add this event and key modifier, then use handleEnterKey as the name for our event handler.

    Our event handler handleEnterKey will add a new ToDoItem object at the beginning of the tasks array (using unshift) and we will reset the inputs value so we can easily add another task afterwards.

    const handleEnterKey = (event: KeyboardEvent): void => {
      const input = (event.target as HTMLInputElement)
      if (!input.value) return
        name: input.value,
        checked: false,
      input.value = ''

    With all of this, we should now have a working to-do list that can add tasks, remove tasks and check/uncheck tasks!

    Need help with a Vue Project?

    Looking for help with your Vue Project? We’re passionate about creating top-quality web applications that stand out from the crowd. Let our skilled development team work with you to bring your ideas to life! Get in touch today and let’s get started!

    Get in Touch

Laravel Partner

Since 2014, we’ve built, managed and upgraded Laravel applications of all types and scales with clients from across the globe. We are one of Europe’s leading Laravel development agencies and proud to support the framework as an official Laravel Partner.

Get in touch

Vue Experts

We use Vue alongside Laravel on many of our projects. We have grown our team of experts and invested heavily in our knowledge of Vue over the last five years.

Get in touch