AJAX pagination with Laravel
Stefan Izdrail
Founder & Senior Architect · 2026-06-29
Title: AJAX Pagination with Laravel: A Comprehensive Approach
Body:
AJAX pagination is an essential technique for creating seamless user experiences in web applications where content is dynamic and requires page-by-page navigation. In this blog post, we will demonstrate how to implement AJAX pagination using Laravel as the backend framework. We assume that you have a basic understanding of Laravel and jQuery.
Firstly, let's review the code provided in the initial response:
$('#posts').on('click', '.pagination a', function(e) {
e.preventDefault();
var url = $(this).attr('href'),
page = url.split('page=')[1],
data = $('#search').serializeArray();
// Adding the new 'page' variable to post data
data.push({page: page});
console.log(data);
$.post($('#search').attr('action'), data, function(data) {
$('#posts').html(data['posts']);
});
});
This JavaScript code listens to clicks on pagination links and sends relevant information (including the page number) to a server-side route. The problem with this is that, in order for Laravel's pagination helper to work properly, you need to pass it through the query string as "page" parameter. To do so, let's modify your code as follows:
$('#posts').on('click', '.pagination a', function(e) {
e.preventDefault();
var url = $(this).attr('href'),
page = url.split('page=')[1]; // Assigning just the value of 'page' from URL
if (isNaN(page)) {
page = 1; // Setting default page to 1 in case 'page' is not a number
}
data = $('#search').serializeArray();
$.post($('#search').attr('action'), data, function(data) {
$('#posts').html(data['posts']);
});
});
Now the code handles both cases, either passing the "page" value from the URL or assigning a default value of 1 if it's not a number. We need to modify your route as well:
@if (Request::ajax())
return Response::json(View::make('includes.posts', ['posts' => Post::search($search)->paginate()])->render()); // Paginating the results with Laravel's paginator helper
@elseif ($request->isMethod('post'))
return ['success' => true, 'message' => 'Search performed']; // If it's a POST request without AJAX, redirect to another view or show success message
@endif
The controller's find() method should be changed to include the pagination logic:
function find($search) {
// ... Previous code
$posts = Post::search($search)->paginate(5);
return View::make('includes.posts', ['posts' => $posts]);
}
Finally, change the HTML in your view:
<div id="posts">
@foreach ($posts as $post)
<div class="list-item clearfix">
<div class="content">
<img src="{{ URL::to($post->thumbnail) }}" alt="" />
<h1>{{{ $post->title }}}</h1>
</div>
<div class="score">{{ $post->rating }}</div>
</div>
@endforeach
<div id="pagination">{{{ $posts->links() }}}</div>
</div>
Now when you click on a pagination link, your view will reload with the corresponding page of results. The next step is to avoid the full page refresh by using AJAX:
$('#posts').on('click', '.pagination a', function(e) {
e.preventDefault();
var url = $(this).attr('href'),
page = url.split('page=')[1];
if (isNaN(page)) {
// Handle invalid 'page' values: show default value of 1 or redirect to another view
} else {
$.post($('#search').attr('action'), $('#search').serializeArray(), function(data) {
$('#posts').html(data['posts']);
// After updating the posts, reload the pagination links using AJAX as well. This will keep the URL consistent and provide a seamless browsing experience:
$.get('{{ route('paginate', ['page' => page]) }}', function(response) {
$('#pagination').html(response);
});
});
}
});
Note that we used a separate route for paginating results (Route::get('paginate', function($page) { return Post::search($search)->paginate($page); })) instead of mixing it with other search-related routes. This keeps things clean and organized.
With this implementation, you will have a smooth AJAX pagination experience on your Laravel application without losing any functionality or performance.