DEV Community

Niles
Niles

Posted on

How To Create A Simple Dynamic Pagination From Scratch In Vue

At some point you might a long array want to separate the content into different pages for users to easily move through the contents so you will have to paginate, while you may use a npm package for pagination, you might also want to create one from scratch like me for efficiency, performance and to not bloat your bundle size, because as we all know an application that is light runs faster and works more efficiently during development and production.
We would be writing our function into an existing Vue3 code.
The first steps is to create an array.

import {ref} from "vue";
const questions = [
  {
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 1,
    bg: "#FFFFFF",
  },
  {
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 2,
    bg: "#F9F2EE",
  },
  {
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 3,
    bg: "#FFFFFF",
  },
  {
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 4,
    bg: "#F9F2EE",
  },
  {
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 5,
    bg: "#FFFFFF",
  },
  {
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 6,
    bg: "#F9F2EE",
  },
  {
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 7,
    bg: "#FFFFFF",
  },
  {
    img: require("@/assets/contact/alao.png"),
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 8,
    bg: "#FFFFFF",
  },
  {
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 9,
    bg: "#F9F2EE",
  },
  {
    desc: "Jessica Gabriel recently posted interview questions for UI/UX Designer",
    date: "Friday 5th, 2022 6:45pm",
    field: "UI/UX Designers",
    id: 10,
    bg: "#FFFFFF",
  },
];
Enter fullscreen mode Exit fullscreen mode

After creating your array, you can go ahead and map it in your template tag.

<template>
<div v-for="item in questions" :key="item.id">
{{ item.field }}
</div>
</template>
Enter fullscreen mode Exit fullscreen mode

The mapped array will show every item on your development server, the next step is to make pagination function. Firstly, you will create your states and assign values to them.

An image of what we will have after mapping through the array

// stores the total number of items in array 
const totalPosts = questions.length;
// stores the total numbers of page the array creates depending of the number of posts per page
const pageNumbers = ref([]);
// total of items to be displayed on one page
const postPerPage = ref(5);
the number of the current page displayed
const currentPage = ref(1);
// setting starting point amd ending point. there is a differnce of 10 if start is 13 end woukd be 23. so in an current post it will be totalArray.value.slice(13,23)
const indexOfLastPost = ref();
const indexOfFirstPost = ref();
//shows the current array displayed
const currentPosts = ref()


indexOfLastPost.value = currentPage.value * postPerPage.value;
indexOfFirstPost.value = indexOfLastPost.value - postPerPage.value;
currentPosts.value = questions.slice(indexOfFirstPost.value, indexOfLastPost.value);
// total number of pages available
const paginateNumber = Math.ceil(totalPosts / postPerPage.value);
Enter fullscreen mode Exit fullscreen mode

You can now change our array in the template to the modified currentPosts array.

<template>
<div v-for="item in currentPosts" :key="item.id">
{{ item.field }}
</div>
</template>
Enter fullscreen mode Exit fullscreen mode

Now you can see only five items in the development server, you can now create our pagination nav.

An image of what we will have after mapping through the splitted array

<script>
for (let i = 1; i <= Math.ceil(totalPosts / postPerPage.value); i++) {
  pageNumbers.value.push(i);
}
</script>
<template>
 <div class="interview__pagination">
      <h6 @click="previous">Previous</h6>
      <div class="numbers">
        <p v-for="item in pageNumbers" :key="item" @click="currentPage = item">
          {{ item }}
        </p>
      </div>
      <h6 @click="next">Next</h6>
    </div>
</template>
Enter fullscreen mode Exit fullscreen mode

You can then go ahead and create your navigation functions.

An image of what we will have after creating the navigation

const previous = () => {
  if (currentPage.value > 1) {
    currentPage.value = currentPage.value - 1;
  }
};
const next = () => {
  if (currentPage.value >= 1 && currentPage.value < paginateNumber) {
    currentPage.value = currentPage.value + 1;
  }
};
Enter fullscreen mode Exit fullscreen mode

Now if you click on the navigation buttons, nothing is going to happen, you have to watch the modified values and update the function as it changes. We will introduce vue watcher into our code.

import { watch } from "vue";
 watch(currentPage, (currentValue, oldValue) => {
      indexOfLastPost.value = currentValue * postPerPage.value;
      indexOfFirstPost.value = indexOfLastPost.value - postPerPage.value;
      console.log(indexOfLastPost.value)
      currentPosts.value = questions.slice(indexOfFirstPost.value, indexOfLastPost.value);
    });
Enter fullscreen mode Exit fullscreen mode

Now, when you click on your navigation, everything works properly.

An image of everything working properly

Top comments (0)