Create a Custom Pagination Component in Laravel Inertia and Tailwind 4

Video thumbnail

In Inertia, we don't have a pagination component to use; so, we have to create one; remember that we left off in this guide on using flash messages in Laravel Inertia.

From the paginated list, we have the links section where all the links for pagination are found in an array:

Paginated Prop Structure

So, we iterate them:

<Link v-for="l in categories.links" :key="l" v-if="!l.active" class="px-2 py-1" :href="l.url" v-html="l.label"/>

To disable the current page and avoid leaving a link that navigates to itself, we can make a conditional and place a SPAN when the current page is used:

<template v-for="l in categories.links" :key="l">
    <Link v-if="!l.active" class="px-2 py-1" :href="l.url" v-html="l.label"/>
    <span v-else class="px-2 py-1"  v-html="l.label"  />
</template>

And add some styling to indicate that it is a disabled link, even though it is really a SPAN tag:

<template v-for="l in categories.links" :key="l">
    <Link v-if="!l.active" class="px-2 py-1" :href="l.url" v-html="l.label"/>
    <span v-else class="px-2 py-1 cursor-pointer text-gray-500"  v-html="l.label"  />
</template>
<script>

From Vue, we have a tag called "Component" with which we can dynamically render components based on a condition evaluated with the is prop:

import Foo from './Foo.vue'
import Bar from './Bar.vue'

export default {
  components: { Foo, Bar },
  data() {
    return {
      view: 'Foo'
    }
  }
}
</script>

<template>
  <component :is="view" />
</template>

With this component in Vue, we can render either Vue or HTML components directly from the component definition:

<Component v-for="l in categories.links" :key="l" :is="!l.active ? 'Link' :'span'" class="px-2 py-1" :class="!l.active ? '' : 'text-gray-500 cursor-pointer'" :href="l.url" v-html="l.label" />

And with this, we have the same result as before, but the syntax is cleaner.

Now, in order to be able to reuse the component globally, we create a new component that receives the paginated list as a parameter using a prop:

resources/js/Shared/Pagination.vue

<template>
    <!-- <Link class="px-2 py-1" v-if="!l.active" :href="l.url">{{ l.label }}</Link>
        <span class="px-2 py-1 cursor-pointer text-gray-500" v-else>{{ l.label }}</span> -->
    <template v-for="l in links" v-bind:key="l">
        
        <Component v-html="`${l.label}`" class="px-2 py-1" :is="!l.active ? 'Link' : 'span'" 
        :href="l.url == null ? '#' : l.url" :class="!l.active ? '' : 'cursor-pointer text-gray-500'"
        />
    </template>
</template>
<script>
import { Link } from '@inertiajs/vue3';
export default {
    components: {
        Link
    },
    props: {
        links: Array
    }
}
</script>

From the category list, we use this component:

resources/js/Pages/Dashboard/Category/Index.vue

***
        <pagination :links="categories.links" />
    </app-layout>
</template>
***
import Pagination from '@/Shared/Pagination.vue'

export default {
    components:{
        AppLayout,
        Link, 
        Pagination
    },
// ***

And we will get:

http://localhost/category?page=1

Custom pagination

Let's learn about the use of another component that, unlike this one, already exists in Inertia: the Progress Bar and spinner.

I agree to receive announcements of interest about this Blog.

We will create a reusable component for pagination in Laravel Inertia with Tailwind 4.

| 👤 Andrés Cruz

🇪🇸 En español