vue | javascript

Vue.js List Rendering : Limit items in v-for

One way to limit the iteration of items in Vue v-for directive.

Abhith RajanFebruary 27, 2018 · 3 min read · Last Updated:

Today I had to render 200+ items in a bootstrap table which didn’t appear to be user-friendly. So I planned to show first 20 of them on load, and if the user wanted, show full items.

To do that, my Vue app code looks like this,

1var app = new Vue({
2 el: "#app",
3 data: {
4 countries: [],
5 isLoadingCountries: false,
6 showLessCountries: true
7 },
8 methods: {
9 getCountries: function() {
10 app.isLoadingCountries = true;
11 app.$http
12 .get("some-url")
13 .then(function(response) {
14 if (response.data) {
15 if (response.data.isSuccess) {
16 app.countries = response.data.countries;
17 }
18 }
19 })
20 .then(function() {
21 app.isLoadingCountries = false;
22 });
23 }
24 },
25 created: function() {
26 this.getCountries();
27 }
28});

Basically, it contains an array, one flag to indicate the data fetch operation is ongoing or not, one flag to indicate whether the full list is showing or fewer items, and a function to fill the data in the array. I hope the naming convention in the code is pretty self-explanatory.

And my markup,

1<table class="table" v-if="!isLoadingCountries">
2 <thead>
3 <tr>
4 <th scope="col">Country</th>
5 </tr>
6 </thead>
7 <tbody v-if="showLessCountries">
8 <tr v-for="country in countries.slice(0, 20)">
9 <td><h5>{{country.name}}</h5></td>
10 </tr>
11 </tbody>
12 <tbody v-else>
13 <tr v-for="country in countries">
14 <td><h5>{{country.name}}</h5></td>
15 </tr>
16 </tbody>
17</table>
18<button
19 v-if="!isLoadingCountries"
20 @@click="showLessCountries = !showLessCountries"
21>
22 {{showLessCountries===true? "Show All Countries" : "Show Less"}}
23</button>

Here, Using Array.slice(), we get a new array with the limited number of items from the original array. And we show the new sliced array items or the original array full items based on the flag. And a button to toggle the flag. If you wonder why I used @@click in Vue, is because my markup was written in Razor (.cshtml).

Update 1 - Sep 6, 2018

As Andrew Butler pointed out in the comments, we can avoid the markup duplication by using a computed property. And the code becomes,

1var app = new Vue({
2 el: "#app",
3 data: {
4 countries: [],
5 isLoadingCountries: false,
6 showLessCountries: true
7 },
8 computed: {
9 countriesToDisplay: function() {
10 if (this.showLessCountries) {
11 return this.countries.slice(0, 10);
12 } else {
13 return this.countries;
14 }
15 }
16 },
17 methods: {
18 getCountries: function() {
19 app.isLoadingCountries = true;
20 app.$http
21 .get("some-url")
22 .then(function(response) {
23 if (response.data) {
24 if (response.data.isSuccess) {
25 app.countries = response.data.countries;
26 }
27 }
28 })
29 .then(function() {
30 app.isLoadingCountries = false;
31 });
32 }
33 },
34 created: function() {
35 this.getCountries();
36 }
37});

And the markup,

1<table class="table" v-if="!isLoadingCountries">
2 <thead>
3 <tr>
4 <th scope="col">Country</th>
5 </tr>
6 </thead>
7 <tbody>
8 <tr v-for="country in countriesToDisplay">
9 <td>
10 <h5>{{country.name}}</h5>
11 </td>
12 </tr>
13 </tbody>
14</table>
15<button
16 v-if="!isLoadingCountries"
17 @@click="showLessCountries = !showLessCountries"
18>
19 {{showLessCountries===true? "Show All Countries" : "Show Less"}}
20</button>

If you know a better way to do the same, let me know.

Additional Resources

Written by Abhith Rajan
Abhith Rajan is an aspiring software engineer with more than 8 years of experience and proven successful track record of delivering technology-based products and services.
Buy me a coffee

Was this article helpful?

Your opinion matters

Please share your thought about this article

This page is open source. Noticed a typo? Or something unclear?
Improve this page on GitHub

Related Videos

Single Page Architectures with VueJS and ASP.NET Core - Kevin Griffin

The Async Await Episode I Promised

Related Stories