Skip to content

Mohcin Bounouara

Thoughts about software engineering and life

Fixing Object Pagination with Laravel and Inertia.js that gives empty data

Problem

When working with Laravel and Inertia.js, pagination returns an object instead of an array. This can make looping over the results a bit tricky, as the expected array structure isn’t accessible.

For example, in a typical Laravel controller method like this:

public function publicIndex()
{
    $latestPosts = Post::orderBy('created_at', 'desc')->paginate(5);

    return Inertia::render('Welcome', [
        'latestPosts' => $latestPosts,
    ]);
}

You might see the data coming through correctly as a prop in your Vue component, but attempting to loop over latestPosts directly results in empty output.

Solution

The issue is due to how Laravel paginate() function structures the data. Instead of a direct array, it returns an object with additional pagination metadata, as this below:

{
  "headers": {},
  "original": {
    "current_page": 1,
    "data": [
      {
        "id": 1,
        "title": "Aspernatur aut assumenda qui ea.",
        "company": "Beatty, Dooley and Klein",
        "created_at": "2024-10-16T17:28:21.000000Z",
        "updated_at": "2024-10-16T17:28:21.000000Z"
      }
    ],
    "total": 1
  },
  "exception": null
}

To access the posts data, you need to use latestPosts.original.data instead of latestPosts directly.

Vue Component Example in this case

To set up your Vue component properly, define the prop as an object and access original.data for looping:

<template>
    <div>
        <ul v-if="latestPosts.original && latestPosts.original.data.length">
            <li v-for="post in latestPosts.original.data" :key="post.id">
                {{ post.title }}
            </li>
        </ul>
    </div>
</template>

<script setup>
import { defineProps } from 'vue';

const props = defineProps({
    latestPosts: {
        type: Object,
        default: () => ({}),
    },
});
</script>

Hope this helps!