Guide on making a reusable pagination child component in VueJS

As a developer, I am currently utilizing Element-UI to speed up the development process of my applications. One feature I want to implement is pagination as a reusable child component within any parent component in order to decrease the overall app size.

For instance, let's consider a parent component with 'inline' pagination.

parent.vue

<template>
    <ol>
        <li v-for="student in studentList>{{ student.full_name }}</li>
    </ol>
    <el-pagination
        layout="sizes, prev, pager, next"
        :total="totalPages"
        :page-size="pageSize"
        :page-sizes="[10, 25, 50, 100]"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange">
    </el-pagination>
</template>
<script>
    export default {
        data () {
            return {
                pageSize: 10,
                currentPage: 1,
                students: [] // this filled from backend when component created
            }
        },
        created () {
            // Axios HTTP request to fetch data from server
            // to filled students variable
        },
        computed: {
            totalPages () {
                return this.students.length
            },
            studentList () {
                return this.students.slice(((this.currentPage - 1) * this.pageSize), (this.pageSize * this.currentPage))
            }
        },
        methods: {
            handleSizeChange (size) {
                this.pageSize = size
            },
            handleCurrentChange (value) {
                this.currentPage = value
            }
        }
    }
</script>

While this method works effectively, it can be tedious having to replicate it in every component that requires pagination. Does anyone have an example of how to create this pagination as a child component while keeping the collections in the parent component?

I've attempted to create a child component but struggled with passing the returned value from a computed property to the parent component.

Take for example my unsuccessful attempt at creating a child component:

child.vue

... // all template elements and functions
computed: {
    studentList () {}
},
methods: {
    updateStudentList () {
        this.$emit('changed-value', this.studentList) // where studentList is a computed function similar to the one in the parent code above
    }
}

parent.vue

// there's no longer a studentList function in the computed property of the parent component
// instead, it has been moved to the child component
<li v-for="student in students">{{ student.full_name }}</li>
<child-pagination v-on:changed-value="rebuildStudent"></child-pagination>
...
methods: {
    rebuildStudent (newCollection) {
       this.students = newCollection
    }   
}

Answer №1

UPDATED

After some experimentation, I was finally able to come up with a solution.

The computed array needs to be stored in the parent component, along with an object that keeps track of the begin and end indexes for slicing the collection array. This object will be updated based on child events using methods.

parent.vue

<template>
    <pagination v-model="pageIndex"
        v-on:paginationInit="paginationInit"
        collections="students">
    </pagination>
</template>

data () {
    return {
        students: [] // collection
        pageIndex: {}
    }
},
computed: {
    studentList () {
        return this.students.slice(pageIndex.begin, pageIndex.end)
    }
},
methods: {
    // This method is emitted from the child component
    paginationInit (pageIndex) {
        this.pageIndex.begin = pageIndex.begin
        this.pageIndex.end = pageIndex.end
    }
}

Then, in the child component, the computed logic was moved into a method that handles events from clicked pagination elements.

child.vue

data () {
    return {
        pageIndex: { begin: 0, end: 10 }
    }
},
created () {
    this.init()
},
methods: {
    init () {
        this.$emit('paginationInit', this.pageIndex)
    },
    handleCurrentChange (page) {
        this.pageIndex.begin = (page - 1) * this.pageSize
        this.pageIndex.end = this.pageSize * page
        this.$emit('input', this.pageIndex)
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A guide to implementing Nuxt.js (SSR) on a specific section of a WordPress (PHP) website

I currently have a WordPress (or PHP) application that is functioning well on every page. Now, I am looking to create a separate application called "marketing" under the segment "/marketing". To achieve this, I am utilizing Nuxt.js to tap into the strength ...

Moving the parent of a ThreeJS object to align with the geometry of its child

I am working with a 3D object that includes a cube mesh as a child. I am trying to adjust the position of the 3D object within the mesh in order to manipulate the pivot points of the cube mesh. You can find the code snippet on this codepen link. ...

Adjusting the position of a stationary element when the page is unresponsive and scrolling

Managing a large web page with extensive JavaScript functionality can be challenging, especially when dealing with fixed position elements that update based on user scroll behavior. A common issue that arises is the noticeable jumping of these elements whe ...

Forward from the Ajax PHP script

I am currently working with a form that looks like this: <form action="process.php" method="post"> <input type="text" name="input" /> <button type="submit">Submit</button> </form> In addition to the form, I have an A ...

What is the process for retrieving the result of a promise at a later time?

var screencastId = 'abc' var a = youtube.get(screencastId); a.then(function(screencast) { // Great, the screencast information is now available. console.log(screencast); }); // How can I access the `screencast` variable below? connection.be ...

Creating a three-row CSS layout where the middle row aligns to the right side

I am working on developing a mobile device layout with 3 blocks. The first and third blocks contain text fields, while the second block is filled with a map. However, all of my blocks don't look good when they are too wide. The browser window can have ...

Aligning images with absolute CSS to text that is wrapping positions the images perfectly alongside the text content

My webpage has a long content section that resizes based on the browser width. Here's an example: <h1 id="loc1">Title</h1> <p>bodycopy bodycopy bodycopy bodycopy bodycopy bodycopy bodycopy bodycopy bodycopy bodycopy bodycopy bod ...

Detecting the State of the Keyboard in Ionic 2

Seeking an easy way to determine if the mobile device keyboard has been opened or closed using Ionic2 and Angular2. Is there a 'keyboard-open' or 'keyboard-close' class that Ionic sends to the body/html? ...

The code is slicing data, but the changes are not reflecting in the user interface

Initially, there are three drop down menus displayed. Upon selecting an option from the first drop down menu, the values in the second drop down menu load. After selecting an option from the second drop down menu, a new set of drop downs appears. However, ...

Retrieve properties of the chosen MenuItem from a Select component in Material UI

My custom component const myUniqueComponent = ({ title, data, errors, onSubmit, groups }) => { const [state, setState] = useState( Object.assign( { username: "", password: "", group: "", isAdmin: false, ...

Update the 'duplicate' buttons according to the position in the array

My app features 14 buttons, each generating a replica button with the same text when clicked. The pre-existing buttons are numbered to aid in iteration. I'm currently attempting to organize the newly created replica buttons in ascending order from lef ...

What could be the reason for the gtag event not showing up in Google Analytics?

Here is an example of my script: <html> <head> <!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-xxxxxxxx-1"></script> <script> wi ...

How can the camera in ThreeJS be shifted horizontally without being affected by its current orientation?

In my ThreeJS setup, the camera is able to move through a 3D world and change its lookAt multiple times while in motion. As a result, camera.getWorldDirection() will always be more or less random. Now, I require the camera to move specifically left, right ...

Tips for obtaining the entire date and time on one continuous line without any breaks or separation

Is there a way to retrieve the current date and time in the format of years, months, days, hours, minutes, seconds, and milliseconds like this? 201802281007475001 Currently, I am getting something like: 2018418112252159 This is my code so far: var dat ...

React function causing website to freeze upon dispatch

I created a function in the child component to handle checkbox selection and trigger setDispatch(true). Unfortunately, whenever I check the checkbox, the website freezes and stops responding until I close and reopen it. Here is the function: const [ ...

Uploading a large number of images to GCP Bucket results in a failure to connect to the oauth2 token

After writing a NodeJS upload function for Google Cloud bucket, I encountered an issue when trying to upload a larger dataset of over 3000 images. Initially, the uploading process seemed smooth, but then suddenly an error occurred and only some of the imag ...

Find a way to avoid Google's site-blocking measures

Currently developing a website. I am looking into restricting access to only logged-in users on the site. How can I parse the pages in a way that Google does not block the site? ...

Using jQuery to target a specific item from a retrieved list of elements

I'm currently working on a photo gallery feature that is reminiscent of Instagram or Facebook user photos. My goal is to enable users to view details about each image (such as the date) in a box that appears over the image when they hover over it. E ...

How to utilize 'this' in a Vue template?

I'm feeling confused: I came across information stating that we can use this in Vue.js templates. But now I'm unsure about which one to use. I decided to experiment with some cases here: new Vue({ el: "#app", data: function() { return { ...

Execute the strace command using the child_process module in Node.js

Having received no answers and being unsatisfied with the previous approach, I am now attempting a different method to monitor the output of a program that is currently running. Inspired by a thread on Unix Stack Exchange, the goal is simply to retrieve th ...