Reputation: 2101
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.
Upvotes: 2
Views: 9766
Reputation: 31
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 :)
Upvotes: 3
Reputation: 2101
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,
]);
}
};
});
}
Upvotes: 3