简体   繁体   English

使用 Vue.Js / Inertia.js 和 Laravel 对结果进行分页

[英]Paginate results with Vue.Js / Inertia.js and Laravel

I'm trying to paginate data from Laravel in Vue.Js.我正在尝试在 Vue.Js 中对来自 Laravel 的数据进行分页。 I'm using Inertia.js as well.我也在使用 Inertia.js。

In my Laravel Controller I have:在我的 Laravel Controller 我有:

    $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.这在 Vue 中连续输出了我的两个用户。 I am also expecting the links object to use for pagination.我也期待链接 object 用于分页。 I don't see this in my Vue props.我在我的 Vue 道具中没有看到这一点。

If I inspect my Vue props I have the following object:如果我检查我的 Vue 道具,我有以下 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:在 controller 我可以看到:

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.我一直在寻找PingCRM的灵感,但没有运气 - 我在链接中引用了。 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.似乎默认的 Laravel 分页不适用于 Inertia.JS,因此您必须前往 AppServiceProvider.php 文件并添加以下内容以使分页正常工作。

This is taken from PingCRM这是取自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.我遇到了类似的问题,并注意到基本的链接()不适用于 Inertia 和 Vue,所以我制作了一个简单的 Vue 组件,在其中我使用了从 Inertia 渲染方法获得的 Paginator Object,它在没有 ServiceProvider 的情况下非常适合我解决方法。

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.然后我将分页器 Object 绑定到我的 Vue 组件,这样我就可以利用它来创建一个基本的分页器组件。 This way I can use and reuse the <Paginator:paginator="paginator" /> anywhere I want.这样我就可以在我想要的任何地方使用和重用<Paginator:paginator="paginator" />

<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.我还创建了一个 package,因此您可以根据需要通过 composer 将其拉入。 See https://github.com/svnwa/InertiaVuePaginator for more Info and the "Components" folder for the paginator component i created.有关更多信息,请参阅https://github.com/svnwa/InertiaVuePaginator以及我创建的分页器组件的“组件”文件夹。 I hope it helps others in the future:)我希望它在未来对其他人有所帮助:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM