DEV Community

Ahmet Meliksah Akdeniz
Ahmet Meliksah Akdeniz

Posted on

Vue.js Basics Part 2 | v-for - List Rendering

This is part 2 of my Basic Vue series. For part 1 click here. Anyways, let's continue

v-for - List Rendering

This code will be a bit long. First, I will share the whole code, after that I will break it down into small chunks.

<script>
// give each todo a unique id
let id = 0

export default {
  data() {
    return {
      newTodo: '',
      todos: [
        { id: id++, text: 'Learn HTML' },
        { id: id++, text: 'Learn JavaScript' },
        { id: id++, text: 'Learn Vue' }
      ]
    }
  },
  methods: {
    addTodo() {
      this.newTodo = {id: id++, text: this.newTodo}
      this.todos.push(this.newTodo)
      this.newTodo = ''
    },
    removeTodo(todo) {
      this.todos = this.todos.filter(item => item.id !== todo.id)
    }
  }
}
</script>

<template>
  <form @submit.prevent="addTodo">
    <input v-model="newTodo">
    <button>Add Todo</button>    
  </form>
  <ul>
    <li v-for="todo in todos" :key="todo.id">
       {{todo.id}} | {{ todo.text }}
      <button @click="removeTodo(todo)">X</button>
    </li>
  </ul>
</template>
Enter fullscreen mode Exit fullscreen mode

Let's get it into smaller pieces

data() {
    return {
      newTodo: '',
      todos: [
        { id: id++, text: 'Learn HTML' },
        { id: id++, text: 'Learn JavaScript' },
        { id: id++, text: 'Learn Vue' }
      ]
    }
  }
Enter fullscreen mode Exit fullscreen mode

To begin with, we need a unique id for each element in the array. So, we create a variable that starts counting from 0 let id = 0. In Vue (and also React), each element must be tracked by their unique keys (:key='').

To add a new todo, we have newTodo: '' that has an empty string as its initial value. We have an array of objects
(todos:[{}, {}, ...]), and each object has key values of id and text. We increment id for each object, so we don't need to hard code.

As we keep reading code above from top to bottom, we will see methods, there're two methods in this todo list; addTodo() and
removeTodo()

addTodo() {
      this.newTodo = {id: id++, text: this.newTodo}
      this.todos.push(this.newTodo)
      this.newTodo = ''
    },
Enter fullscreen mode Exit fullscreen mode

With addTodo() function we access to todos array and push a new object inside of it. Since todos is an array of objects we must pass in an object when pushing, otherwise it won't work. After pushing we again assign an empty string to this.newTodo, so the old added value won't remain inside the input. Otherwise, you will see this [object Object].

Now let's remove our todos

removeTodo(todo) {
       this.todos = this.todos.filter(item => item.id !== todo.id)
    }
Enter fullscreen mode Exit fullscreen mode

We create a function that takes todo as its parameter. Todo is the one that picks a todo to remove when the X button is clicked. Onto inside of our code block.

First, I will explain the right side of the assignment operator (=). We filter our todos array. The .filter()method takes one parameter; item. The item parameter loops over each element of the array and compares if the current item is not equal to todo (that is clicked by the user). We get a hang of todo by clicking on the X button. So, item => item.id !== todo.id removes the clicked item.

Finally, last chunk of our code:

<template>
  <form @submit.prevent="addTodo">
    <input v-model="newTodo">
    <button>Add Todo</button>    
  </form>
  <ul>
    <li v-for="todo in todos" :key="todo.id">
       {{todo.id}} | {{ todo.text }}
      <button @click="removeTodo(todo)">X</button>
    </li>
  </ul>
</template>
Enter fullscreen mode Exit fullscreen mode

@submit.prevent prevents forms from refreshing pages when form is submitted. Then, we've got an input tag that is two-way-binded to newTodo data. v-model: is responsible for syncing newTodo data and addTodo() function. Outside of our form we have got a list tag.

Here's how v-for works in a list tag:

As you see there's todo in todos. Yes, we've got todos array, but what is todo? It's a local variable that will be alive only in this

  • tag because it's created in it. That means, todo is not accesible outside of
  • in this case. So, we've got an array of objects, by using v-for, we iterate over objects in todos array. So, todo represents each object in todos array. Since todo is a local variable, we can name it however we wish, but understandable naming is one of the best practices. For instance, if I had an array of books, I would have coded it as <li v-for="book in books" :key="book.id"> ... </li>.
  • Top comments (0)