In this guide we will explain how you can use the Laravel pagination with ajax so your webpage doesn't reload when you select a page, or click the next / prev buttons.
Pagination is useful when you need your web framework to return a large number of results, usually in a table format. Returning all results at the same time not only won't allow you to have a minimalist page, but more importantly it will put too much load on your database.
Laravel contains a paginator which is integrated with their query builder and ORM (database wrapper) which makes pagination a breeze.
Let's say you have a large database table called transactions
, with a million entries.
The Laravel paginator
allows you to simply call your object like the following. In this case 25
would be the maximum returned per page:
$transactions = DB::table('transactions')->paginate(25);
In your view you might create a table:
<table>
<thead>
<th>Amount</th>
<th>Date</th>
<th>ID</th.
</thead>
<tbody>
@foreach ($transactions as $transaction)
<tr>
<td>{{ $transactions->amount }}</td>
<td>{{ $transactions->date }}</td>
<td>{{ $transactions->id }}</td>
</tr>
@endforeach
</tbody>
</table>
... And finally, you would echo the actual pagination html somewhere:
{{ $transactions->links() }}
This works really well out of the box, however every time you go to another page, the entire page will reload - with the GET variable ?page=X
triggering which page to load.
Better than this would be to have ajax page transitions so the entire web page does not have to reload.
As this works well out of the box, we will try to utilize as much existing functionality as possible.
In this tutorial, we will make the following assumptions:
transactions
, with three fields: id
, date
and amount
.TransactionController
public function table()
table.blade.php
) and assigned the appropriate routes.transactions_table_only
.public function table()
{
$transactions = DB::table('transactions')->paginate(25);
return view("table", compact("transactions"));
}
{{ $transactions->links() }}
<table>
<thead>
<th>Amount</th>
<th>Date</th>
<th>ID</th.
</thead>
<tbody>
@foreach ($transactions as $transaction)
<tr>
<td>{{ $transactions->amount }}</td>
<td>{{ $transactions->date }}</td>
<td>{{ $transactions->id }}</td>
</tr>
@endforeach
</tbody>
</table>
We need to do this as Javascript needs to directly interface with the $transactions
object, and only the table html should be regenerated.
Change your controller to:
public function table()
{
return view("table");
}
// New function for handling AJAX:
public function get_table(Request $request)
{
$currentPage = $request->page_num;
// Set the paginator to the current page
Paginator::currentPageResolver(function() use ($currentPage) {
return $currentPage;
});
$transactions = DB::table('transactions')->paginate(25);
return view("transactions_table_only", compact("transactions"));
}
Note the Paginator::currentPageResolver
call which sets the current page to the variable $page
.
This needs to be done as the table needs to be reloaded via AJAX.
Move the entire <table> ... </table>
, and {{ $transactions->links() }}
to this file. We've assumed you called it transactions_table_only.blade.php
.
Now, in your newly created view you will need to override the default pagination behavior - by stopping the <a href="./?page=x">
tags from working.
You can do this with the following Javascript in transactions_table_only
:
<script>
$(function() {
$(".pagination a").click(function() {
return call_post_func($(this).attr('href'));
});
});
function call_post_func(href)
{
console.log(href);
post_this(href)
return false;
}
</script>
Assuming you've called your function post_this
, we now have to send our Controller a POST request, and update the HTML.
Add this function within the original view table.blade.php
:
<script>
post_this(page_num)
{
$.post("/ajax/update_transaction_table", {
"_token": "{{ csrf_token() }}",
"page_num": page_num
},
function(result){
$("#search_result").html(result)
})
}
Ensure you've updated your routes file to route the POST request /ajax/update_transaction_table
to the controller function get_table()
.
That's it! Your view should now update via AJAX, without reloading the page.