Where is defined allTags ? I don't see it in your code.
Aug 29, 2025
3
Level 5
Infinite Scrolling
I'm trying to implement infinite scroll per Jeffrey's video and I don't have it quite right. I am paginating my Tag model and returning some other metadata to the page.
public function index()
{
$tags = Tag::query()
->withCount('posts')
->orderBy('posts_count', 'desc')
->orderBy('name')
->paginate(15);
// Get stats for the initial page load only
$totalTags = request()->get('page', 1) == 1
? Tag::count()
: null;
$totalPosts = request()->get('page', 1) == 1
? Tag::withCount('posts')->get()->sum('posts_count')
: null;
return Inertia::render('Tags/Index', [
'tags' => Inertia::merge($tags->items()), // Merge the tags with the pagination data
'pagination' => [
'current_page' => $tags->currentPage(),
'last_page' => $tags->lastPage(),
'has_more_pages' => $tags->hasMorePages(),
'per_page' => $tags->perPage(),
'total' => $tags->total(),
],
'totalTags' => $totalTags,
'totalPosts' => $totalPosts,
]);
}
I'm defining some interfaces and the props like so:
interface Tag {
id: number;
name: string;
slug: string;
color: string;
description?: string;
posts_count: number;
}
interface Pagination {
current_page: number;
last_page: number;
has_more_pages: boolean;
per_page: number;
total: number;
}
const props = defineProps<{
tags: Tag[];
pagination: Pagination;
totalTags?: number;
totalPosts?: number;
}>();
And I'm trying to perform infinite scrolling like this
<div v-if="filteredTags.length > 0" class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<Link
v-for="tag in allTags"
:key="tag.id"
:href="`/tags/${tag.slug}`"
class="group block rounded-lg border bg-card p-4 transition-all hover:border-primary/50 hover:shadow-md"
>
<div class="flex items-start justify-between">
<div class="flex-1">
<div class="flex items-center space-x-3">
<div :style="{ backgroundColor: tag.color }" class="h-4 w-4 flex-shrink-0 rounded-full" />
<h3 class="font-medium transition-colors group-hover:text-primary">
{{ tag.name }}
</h3>
</div>
<p v-if="tag.description" class="mt-2 line-clamp-2 text-sm text-muted-foreground">
{{ tag.description }}
</p>
</div>
<Badge :style="{ backgroundColor: tag.color + '20', color: tag.color }" class="ml-2 flex-shrink-0">
{{ tag.posts_count }} {{ tag.posts_count === 1 ? 'post' : 'posts' }}
</Badge>
</div>
</Link>
</div>
<!-- Infinite Scroll Loader -->
<WhenVisible
:always="!reachedEnd"
:buffer="100"
:params="{
only: ['tags', 'pagination', 'totalTags', 'totalPosts'],
data: {
page: pagination.current_page + 1,
},
preserveUrl: true,
}"
>
<div class="py-8 text-center">
<div class="inline-flex items-center space-x-2 text-muted-foreground">
<div class="h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent"></div>
<span class="text-sm">Loading more tags...</span>
</div>
</div>
</WhenVisible>
When I scroll to the buffer, I can see the Loading spinner and text, and in the Vue dev tools, I can 100% see that the tags Array is being appended to, but the actual Card items I have in the divs aren't rendering the other Tag models.
What am I missing?
Please or to participate in this conversation.