I'm trying to paginate data from Laravel in Vue.Js. I'm using Inertia.js as well.
In my Laravel Controller I have:
$data['participants'] = User::with('groups')->select('id', 'name')->paginate(2);
return inertia('Dashboard/Participants', $data);
This outputs my two users in a row well in Vue. I am also expecting the links object to use for pagination. I don't see this in my Vue props.
If I inspect my Vue props I have the following object:
participants:Object
current_page:1
data:Array[2]
first_page_url:"http://localhost:3000/dashboard/participants?page=1"
from:1
last_page:51
last_page_url:"http://localhost:3000/dashboard/participants?page=51"
next_page_url:"http://localhost:3000/dashboard/participants?page=2"
path:"http://localhost:3000/dashboard/participants"
per_page:2
prev_page_url:null
to:2
total:101
If I:
dd($data['participants']->links());
in the controller I can see:
Illuminate\View\View {#316 ▼
#factory: Illuminate\View\Factory {#310 ▶}
#engine: Facade\Ignition\Views\Engines\CompilerEngine {#328 ▶}
#view: "pagination::bootstrap-4"
#data: array:2 [▶]
#path: "/Users/ejntaylor/Documents/Laravel/motional/vendor/laravel/framework/src/Illuminate/Pagination/resources/views/bootstrap-4.blade.php"
}
I have been looking at PingCRM for inspiration but without luck - I've referenced in the link. Help appreciated.
It would seem the default Laravel pagination does not work with Inertia.JS so you must head to your AppServiceProvider.php file and add the following to get pagination to work.
This is taken from PingCRM
protected function registerLengthAwarePaginator()
{
$this->app->bind(LengthAwarePaginator::class, function ($app, $values) {
return new class(...array_values($values)) extends LengthAwarePaginator {
public function only(...$attributes)
{
return $this->transform(function ($item) use ($attributes) {
return $item->only($attributes);
});
}
public function transform($callback)
{
$this->items->transform($callback);
return $this;
}
public function toArray()
{
return [
'data' => $this->items->toArray(),
'links' => $this->links(),
];
}
public function links($view = null, $data = [])
{
$this->appends(Request::all());
$window = UrlWindow::make($this);
$elements = array_filter([
$window['first'],
is_array($window['slider']) ? '...' : null,
$window['slider'],
is_array($window['last']) ? '...' : null,
$window['last'],
]);
return Collection::make($elements)->flatMap(function ($item) {
if (is_array($item)) {
return Collection::make($item)->map(function ($url, $page) {
return [
'url' => $url,
'label' => $page,
'active' => $this->currentPage() === $page,
];
});
} else {
return [
[
'url' => null,
'label' => '...',
'active' => false,
],
];
}
})->prepend([
'url' => $this->previousPageUrl(),
'label' => 'Previous',
'active' => false,
])->push([
'url' => $this->nextPageUrl(),
'label' => 'Next',
'active' => false,
]);
}
};
});
}
I had a similar problem and noticed the basic links() wouldn't work with Inertia and Vue so i made a simple Vue component where I use the Paginator Object I get from the Inertia render method and it works very well for me without the ServiceProvider workaround.
I can just use
public function index()
{
return Inertia::render('MyUserList',[
'paginator' => User::paginate(10)
]);
}
as I normally would. Then i bind the paginator Object to my Vue Component so I can leverage it to create a basic Paginator component. This way I can use and reuse the <Paginator:paginator="paginator" />
anywhere I want.
<template>
<Paginator :paginator="paginator" />
</template>
<script>
import Paginator from "@/Components/Paginator";
export default {
props: {
paginator: Object
},
}
</script>
I also created a package so you can pull it in via composer if you want. See https://github.com/svnwa/InertiaVuePaginator for more Info and the "Components" folder for the paginator component i created. I hope it helps others in the future:)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.