Iterating Over Items in Vue.js With V-for

Listing out items, from a simple to-do list to a complex card system is a common requirement for front-end applications. Vue.js supports rendering lists of items onto the browser using the built-in v-for core directive.

Starting off with the Vue.js Hello World application, we can add data that can then be repeated using v-for.

data() {
  return {
    messages:  ['hello', 'vue', 'js'],
    shoppingItems: [
      {name: 'apple', price: '10'},
      {name: 'orange', price: '12'}
    ]
  }
}

V-for

The built-in v-for directive allows us to loop through items in an array or object.

We can loop over items in our messages array from the data model. This can be done by adding the v-for directive in the element that should be repeated.

<ul>
  <li v-for="msg in messages">{{ msg }}</li>
</ul>

This will output an unordered list with the values from the array.

Similarly, we can loop over the objects in the shoppingItems array. Here we can access the values using a given key (ex- item.name).

<ul>
  <li v-for="item in shoppingItems">
    {{ item.name }} - {{ item.price }}
  </li>
</ul>

<template> element

The v-for directive only applies to the element that it’s attached to. If multiple items should repeat with the v-for directive, we should wrap the elements in a <template> element.

<template v-for="item in shoppingItems">
  <label> {{ item.name }} </label>
  <label> {{ item.price }} </label>
  <button>Buy</button>
</template>

V-for with Objects

We can loop over objects with multiple properties like we do with arrays:

data() {
  return {
    objectItems: {
      key1: 'item1',
      key2: 'item 2',
      key3: 'item3'
    }
  }
}
<ul>
  <li v-for="item in objectItems">{{ item }}</li>
</ul>

In the above example, we’re printing out the items (‘item1’, ‘item2’, ‘item3’).

In addition to the property value, we get two additional parameters when looping over objects with Vue. Namely, the key and the index values.

<ul>
  <li v-for="(item, key, index) in objectItems">
    {{ item }} - {{ key }} - {{ index }}
  </li>
</ul>

The key value gives us access to the current properties key (‘key1’, ‘key2’, ‘key3’).

The index provides us the index of the current item in the loop. This is simply the position of the item in the looped list (0, 1, 2).

V-for with Range

We can use a range in the v-for directive to iterate a specified number of times.

The following syntax would print out 1 to 15 in an unordered list:

<ul>
  <li v-for="item in 15">{{ item }}</li>
</ul>

Key

When the array order is changed, by default Vue would change the data in each existing element rather than moving the DOM elements to the updated position.

We can set Vue to track each element using a key. This would cause it to move elements rather than replacing values.

This value should be unique to each element that’s being iterated over:

<ul>
  <li v-for="item in shoppingItems" :key="item.name">
    {{ item.name }} - {{ item.price }}
  </li>
</ul>

Managing changes

Out of the box v-for supports array mutation methods. These are push, pop, shift, unshift, splice, sort and reverse. If any of these operations are performed on an array, the v-for directive updates the view with the new data.

Also, when we replace an array with a new array, Vue finds the most optimized way to update the items.

Problems with change management

The two things that Vue can’t track when changed in an array are,

1. Setting items directly

ex: data.shoppingItems[3] = {price: 10, name: 'pineapple'}

This can be resolved by using the Vue.set method. This method accepts the array, an index and the new value.

Vue.set(data.shoppingItems, 3, {price: 10, name: 'pineapple'});

Also, we can use splice to set the value at a given index.

2. Modifying array length

ex: data.shoppingItems.length = 2

We can use Splice to modify the array length instead of setting it directly to avoid issues.

Filtering list

We can filter out lists that are being displayed without changing the original list. This can be done using computed values or simply by having a method and passing values through when setting the v-for values.

Using computed values to filter items

Instead of setting the value directly on the list, we instead point to a computed value. We can write the logic for filtering out data in that computed function.

<ul>
  <li v-for="item in itemsLessThanTen" :key="item.name">
    {{ item.name }} - {{ item.price }}
  </li>
</ul>
data() {
  return {
    shoppingItems: [
      {name: 'apple', price: '7'},
      {name: 'orange', price: '12'}
    ]
  }
},
computed:{
  itemsLessThanTen: function() {
    return this.shoppingItems.filter(function(item) {
      return item.price > 10;
    })
  }
}

The itemLessThanTen function simply uses the JS filter function to return any item who’s price is less than 10.

Using a method to filter items

In this approach, we pass in the same shoppingItems list directly to a method that we define. By doing so, all the items in the array would be filtered according to the method definition.

<ul>
  <li v-for="item in filterItems(shoppingItems)" :key="item.name">
    {{ item.name }} - {{ item.price }}
  </li>
</ul>

Here, we are passing the shoppingItems list though the filterItems method.

data() {
  return {
    shoppingItems: [
      {name: 'apple', price: '7'},
      {name: 'orange', price: '12'}
    ]
  }
},
methods:{
  filterItems: function(items) {
    return items.filter(function(item) {
      return item.price > 10;
    })
  }
}

The filterItems method performs the same function as in the computed value example and the final result would be the same.

Search

🔎 Searching...