Vue.js Basics Part 2 | v-for - List Rendering
Published: 2022-08-30 16:01:02

This is part 2 of my Basic Vue series. For part 1 click [here](https://dev.to/ahmetmeliksah/vuejs-baiscs-part-1-5glm). 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>
```
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' }
      ]
    }
  }
```

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 = ''
    },
```

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)
    }
```

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>
```

`@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 <li> tag because it's created in it. That means, `todo` is not accesible outside of <li></li> 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>`.