DEV Community

indiejesus2
indiejesus2

Posted on

Adding Pagination with VanillaJS

After completing my bootcamp at Flatiron, it was suggested that I go back to previous projects to refactor and perhaps update them. I first attempted playing around with my Frisbee Golf application that was made with VanillaJS frontend and a Ruby on Rails backend. To test a new feature I developed with comments, I created too many golf course cards that littered the page. It got me thinking what would happen if this were a live app and there were hundreds of golf course cards created, would it become an endless scroll?

As so happens with life, I left that question on the back burner while I pursued other outlets including learning Next.js through the Advanced React course by Wes Bos. Within the course, he teaches you how to implement pagination in order to allow the index page to be more manageable. I thought it was a brilliant idea and I immediately thought that it would be a great feature for my Frisbee Golf app.

I soon came to the realization that while it wasn’t too hard to develop this feature with Next.js and ApolloGQL, it wouldn't be so easy translating it to VanillaJS format. But where there is a will, there is a way, and I was certainly up for the challenge to add pagination to my application.

After configuring a new bare bones component that would strictly handle the pagination feature, the first step I began with was querying how many courses were in the database to then determine how many pages would be available to scroll through. My SPA was set up with four courses being displayed when the window was in full-screen, therefore I thought having eight courses displayed on a page would be plenty. This also presented my first challenge, how was I going to pass along the data between the two components?

My application was originally set up where the query function to gather the courses data from the backend was performed in the Course Info component, The received data was then iterated over as each course was then rendered into its own separate card. I found it difficult to determine how to pass data length to the pages, and then communicate which courses should be currently displayed based on the page selection.

I eventually decided that the best way to determine how many pages would be needed along with cycling through the cards was to query the data right in the Course Pagination component. In the constructor of the component, I declared the variables for how many pages would be created based on the amount of courses, as well as declaring the default page to 0. I also initialized the first batch of courses through a renderCourses() function called within the constructor method.

    renderCourses(page = 0) {
        let courses = []
        let i = page
        while (courses.length < 8) {
            courses.push(this.pages[i])
            i++ 
        }
        let cards = document.getElementsByClassName("card")
        if (cards.length > 1) {
            while(cards.length > 0) {
                cards[0].remove()
            }
        }
        courses.forEach(course => new CourseInfo(course))
        this.renderPage()
    }
Enter fullscreen mode Exit fullscreen mode

The render course function would be given the page parameter, then create an empty array that would be filled with the appropriate amount of 8 courses. I determined that if I wanted to display the first eight courses found within the data, item 0 through 7 would be found within the array, and if the second page was selected then item 8 through 15 would be selected for the right. Therefore the page number would start at zero, and when the next page was selected, the page number would increase by 1. The page number was then multiplied by 8 so then the courses array would then push each individual course starting with the eighth item.

    handleOnClick = (e) => {
        if (e.target.className == "next") {
            if ((this.page+1) != this.count) {
                this.page += 1
                this.renderCourses(this.page*8)
            }
        } else if (e.target.className == "last") {
            if (this.page != 0) {
                this.page -= 1
                this.renderCourses(this.page*8)
            }
        }
    }
Enter fullscreen mode Exit fullscreen mode

The cards were being cycled through, but instead of the first batch being replaced by the next batch, it was simply being added on. As is necessary in JavaScript I needed to first remove the list of courses before rendering a new batch of courses. I simply iterated through the elements and removed each card before initializing new courses through the course info component.

The next challenge I came across was updating what page the index was on. Again, with React or Next, the document would display the correct page number when the courses were updated, but VanillaJS doesn’t include this magical feature. Every time a new batch of courses is rendered, the header containing the current page number would have to be removed and appended again. Thankfully, the process is seamless as if the whole thing is intuitive.

    renderPage() {
        const old = document.getElementsByClassName("pagination")
        if (old.length > 0) {
            old[0].remove()
        }
        const head = document.createElement("header")
        head.innerHTML = this.renderHTML(this.page, this.count);
        this.constructor.container.append(head);
    }
Enter fullscreen mode Exit fullscreen mode

Now my single page application is not littered with countless courses. it Cycles through them seamlessly and looks much cleaner. At first what I thought would be an impossible challenge turned out to be a little less complex than I expected to see, but I was still proud of myself nonetheless.
n the constructor method.

Discussion (0)