DEV Community

Cover image for Gridsome Pagination
Chuck
Chuck

Posted on

Gridsome Pagination

When ever I set up a blog, there are a few features which are must haves, linkable taxonomy (i.e. tags or categories) and pagination. No one wants an eternal page. These tasks can be challenging but it is super easy in Gridsome.

What is Gridsome?

Gridsome is the Gatsby alternative for Vue.js that aims to provide the tech stack to build blazing fast statically generated websites. It’s data-driven, using a GraphQL layer to get data from different sources in order to dynamically generate pages from it. 1 Adding pagination to this blog was the easiest implementation I have experienced. It requires basically three separate parts.

  • GraphQL
  • New Component
  • Add CSS Styling

GraphQL

In Gridsome, the GraphQL query handles the data collection. Where is a standard Vue.js application you might handle pagination in the Script section, via data and methods, in Gridsome all of the heavy lifting is done in the data later, which in this case in GraphQL. Notice below in my page-query there are three differences from the standard query:

  • Declare a $page query variable
  • Define the number of items perPage
  • Add @pagination directive
  • Include totalCount and the pageInfo section as shown below
query ($page: Int) {
  posts: allPost(perPage: 5, page: $page, filter: { published: 
    { eq: true }}) @paginate {
    totalCount
    pageInfo { 
      totalPages 
      currentPage 
      isFirst 
      isLast 
      } 
    edges { 
      node { 
      id 
      title 
      date (format: "MMM DD, YYYY")
      timeToRead 
      description 
      cover_image (width: 770, height: 380, blur: 10) 
      path tags { 
      id 
      title 
      path 
          } 
        } 
      } 
    } 
  }
Enter fullscreen mode Exit fullscreen mode

Add Component

Next task is to add the Pager component from Gridsome. In the script section:

import { Pager } from 'gridsome'

export default {
  components: {
    Pager
  }
 }
Enter fullscreen mode Exit fullscreen mode

Then at the bottom of the template section add the Pager component:
<Pager :info="$page.posts.pageInfo" />

Add Styling

Now, the output has no styling so we need to handle that with properties available on the Pager Component.
First to style the links, you can add a :linkClass to style the pagination links. But you will need to also include a second class to style the pagination container. So, my Pager element looks so:

<Pager :info="$page.posts.pageInfo" 
       linkClass="pager__link" 
       class="pager" />
Enter fullscreen mode Exit fullscreen mode

My styling to match my theme looks so:

<style lang="scss">
  .pager {
    display: inline-block;
    width: 100%;
    text-align: center;

    &__link {
      color: var(--link-color);
      text-align: center;
      text-decoration: none;
      padding: .5rem 1rem;

      &:hover:not(.active) {
        background-color: var(--bg-content-color);
        border-radius: 5px;
        color: var(--link-color);
      }
    }
  }

  .active {
    background-color: var(--bg-content-color);
    border-radius: 5px;
  }

</style>
Enter fullscreen mode Exit fullscreen mode

All Done!
Notice the styling? What I like about the Gridsome Blog Starter is that all the styles use SCSS and Block Element Modifier (BEM) naming convention, so my styling follows this convention.
Enjoy and I hope this helps.

1. Credit to Building a blog with Gridsome by Alex Morales.

Top comments (10)

Collapse
 
hizbe profile image
Muhammad Hizbullah • Edited

#ask

if I'll to filter data in taxonomy pages, example :
I'll get a list of post where tag is A, then I'll filter it with published: true.

query ($page: Int) {
  category {
    title
    belongsTo(perPage: 10, page: $page) @paginate {
      pageInfo {
        totalPages
        currentPage
      }
      edges {
        node {
          ... on Post {
            id
            title
            path
          }
        }
      }
    }
  }
}

when I filter it use this

query Tag ($id: ID!, $page: Int) {
  tag (id: $id) {
    title
    belongsTo (perPage: 2, page: $page, sortBy: "date", filter: { published: {eq: true} }) @paginate {
        totalCount
        pageInfo {
            totalPages
            currentPage            
        }
        edges {
            node {
                ...on Post {
                    title
                    path
                    date (format: "D MMMM YYYY")
                    timeToRead
                    description
                    content
                }
            }
        }
    }
  }
}

I get Error in terminal Field "published" is not defined by type BelongsToFilterInput
how can I filter and solve it?

Collapse
 
eclecticcoding profile image
Chuck

So, I added the published feature to my blog site. You will need to add the following to the gridsome.server.js file. It will add the filter, but will ignore the published field in your development server:

module.exports = function(api) {
  api.loadSource(store => {
    if (process.env.NODE_ENV === 'production') {
      const posts = store.getContentType('Post')

      posts.data().forEach(node => {
        if (node.published !== true) {
          posts.removeNode(node.id)
        }
      })
    }
  })
}
Collapse
 
hizbe profile image
Muhammad Hizbullah

oke solved, thank's.

Thread Thread
 
eclecticcoding profile image
Chuck

Great I am glad this helped.

Collapse
 
djmtype profile image
Scott Rod

Any way of paginating by year?

Collapse
 
karam profile image
Karam Kabbara

This was really helpful, thank you!

Collapse
 
eclecticcoding profile image
Chuck

Glad I was able to help

Collapse
 
lowell130 profile image
Stew

love this, thank you!

Collapse
 
saikiruthi profile image
saikiruthi

Hii,

How to paginate based on search result count. I couldn't able to get total count based on the search results.

Collapse
 
saikiruthi profile image
saikiruthi

Is it possible to add three dots in pagination