I have faced this issue lately with several thousand rows needing to be returned in some areas. I am using Vue.js for my client side, so here's a rough idea of how I'm currently doing it:
routes.php
//Page route
Route::get('/getsomerows', function() {
return view('myview');
});
//AJAX route
Route::post('/getsomerows', 'myController@getSomeRows');
myController.php
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
class myController extends Controller
{
public function getSomeRows()
{
$rows = \App\SomeModel::paginate(15);
return response()->json([
'status' => 'success',
'errors' => false,
'data' => [
'rows' => json_decode($rows->toJson()),
'paginationMarkup' => $rows->render()
]
], 200);
}
}
myview.blade.php
<div id="vue-container">
<ul v-if="rows">
<li v-for="row in rows">
@{{ row.someData }}
@{{ row.someMoreData }}
</li>
</ul>
{{-- notice the triple curly braces here - this will properly render the markup --}}
<div>@{{{ pagination.markup }}}</div>
</div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.17/vue.min.js"></script>
<script type="text/javascript" src="myview.js"></script>
myview.js
//setup vue instance
var $v = new Vue({
el: '#vue-container',
data: {
rows: [],
pagination: {
markup: '',
currentPage: -1
}
},
methods: {
getRows: function(page) {
if (!isNaN(page) && page > 0) {
page = '?page=' + page;
} else {
page = '';
}
$.ajax({
url: '/getsomerows' + page,
method: 'POST',
dataType: 'json'
}).done(function(response) {
if (response.status == 'success' && Object.keys(response.data.rows).length > 0) {
$v.rows = response.data.rows.data;
$v.pagination.currentPage = response.data.rows.current_page;
$v.pagination.markup = convertPaginationMarkup(response.data.paginationMarkup, $v.pagination.currentPage, '$v.getRows');
} else {
$v.rows = [];
$v.pagination.currentPage = -1;
$v.pagination.markup = '';
}
});
}
}
});
//handle AJAX supplied pagination - this can be moved to your main app library and used on other pages
function convertPaginationMarkup(markup, currentPage, onClickMethod) {
var miniDOM = $(markup);
//remove HREFs and add vue code
$.each(miniDOM.find('a'), function() {
var $link = $(this), linkValue = $link.html();
//parse link value - is actual page number that we're after
if (isNaN(parseInt(linkValue))) {
if (linkValue === '»') {
fetchPage = currentPage + 1;
}
if (linkValue === '«') {
fetchPage = currentPage - 1;
}
} else {
fetchPage = parseInt(linkValue);
}
//remove straight up href
$link.attr('href', 'javascript:void(0)');
//add onclick event to load next page via AJAX rather than straight up href
$link.attr('onclick', onClickMethod + '(' + fetchPage + ')');
});
//use the innerHTML of a DOM clone to convert the HTML object to HTML string
return $('<div>').append(miniDOM.clone()).html();
}
This works fine on two projects I'm working on and seems pretty responsive. Your mileage may vary, but hopefully this will at least point you in the right direction :)