starfolksoftware / inertia-table
Inertia.js 前端组件,用于 Spatie 的 Laravel 查询构建器
Requires
- php: ^8.1|^8.2
- illuminate/support: ^9.37|^10.0|^11.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.8
- inertiajs/inertia-laravel: ^0.6.9
- orchestra/testbench: ^7.0|^8.0
- phpunit/phpunit: ^9.5
README
特性
- 自动填充:自动生成带有自定义单元格支持的
thead
和tbody
- 全局搜索
- 按字段搜索
- 选择过滤器
- 切换列
- 排序列
- 分页(支持 Eloquent/API Resource/Simple/Cursor)
- 自动更新查询字符串(通过使用 Inertia 的 replace 功能)
兼容性
- Vue 3
- Laravel 9
- Inertia.js
- Tailwind CSS v3 + Forms 插件
- PHP 8.0+
注意:目前在使用此包与 Vite 一起使用时存在一个 问题!
安装
您需要安装服务器端包和客户端包。请注意,此包仅与 Laravel 9、Vue 3.0 兼容,并需要 Tailwind Forms 插件。
服务器端安装(Laravel)
您可以通过 composer 安装此包
composer require starfolksoftware/inertia-table
该包将自动注册 Service Provider,它提供了一个您可以在 Inertia 响应中使用的 table
方法。
搜索字段
使用 searchInput
方法,您可以指定哪些属性是可搜索的。搜索查询作为 filter
传递到 URL 查询中。这与 Laravel 查询构建器包的 过滤功能无缝集成。
尽管传递列键就足够了,但您也可以指定自定义标签和默认值。
use InertiaTable\InertiaTable; Inertia::render('Page/Index')->table(function (InertiaTable $table) { $table->searchInput('name'); $table->searchInput( key: 'framework', label: 'Find your framework', defaultValue: 'Laravel' ); });
选择过滤器
选择过滤器与搜索字段类似,但使用 select
元素而不是 input
元素。这样,您可以向用户展示一组预定义的选项。底层,它使用与 Laravel 查询构建器包相同的过滤功能。
selectFilter
方法需要两个参数:键和一个包含选项的键值数组。
Inertia::render('Page/Index')->table(function (InertiaTable $table) { $table->selectFilter('language_code', [ 'en' => 'Engels', 'nl' => 'Nederlands', ]); });
默认情况下,selectFilter
会向数组添加一个 无过滤器 选项。您可以禁用此选项或为其指定一个自定义标签。
Inertia::render('Page/Index')->table(function (InertiaTable $table) { $table->selectFilter( key: 'language_code', options: $languages, label: 'Language', defaultValue: 'nl', noFilterOption: true, noFilterOptionLabel: 'All languages' ); });
列
使用 column
方法,您可以指定哪些列可以切换、排序和搜索。您必须为每个列至少传递一个键或标签。
Inertia::render('Page/Index')->table(function (InertiaTable $table) { $table->column('name', 'User Name'); $table->column( key: 'name', label: 'User Name', canBeHidden: true, hidden: false, sortable: true, searchable: true ); });
searchable
选项是 searchInput
方法的快捷方式。下面的示例实际上将调用 $table->searchInput('name', 'User Name')
。
全局搜索
您可以使用 withGlobalSearch
方法启用全局搜索,并可选地指定一个占位符。
Inertia::render('Page/Index')->table(function (InertiaTable $table) { $table->withGlobalSearch(); $table->withGlobalSearch('Search through the data...'); });
如果您想默认为每个表格启用全局搜索,您可以使用静态 defaultGlobalSearch
方法,例如,在 AppServiceProvider
类中
InertiaTable::defaultGlobalSearch(); InertiaTable::defaultGlobalSearch('Default custom placeholder'); InertiaTable::defaultGlobalSearch(false); // disable
示例控制器
<?php namespace App\Http\Controllers; use App\Models\User; use Illuminate\Support\Collection; use Inertia\Inertia; use InertiaTable\InertiaTable; use Spatie\QueryBuilder\AllowedFilter; use Spatie\QueryBuilder\QueryBuilder; class UserIndexController { public function __invoke() { $globalSearch = AllowedFilter::callback('global', function ($query, $value) { $query->where(function ($query) use ($value) { Collection::wrap($value)->each(function ($value) use ($query) { $query ->orWhere('name', 'LIKE', "%{$value}%") ->orWhere('email', 'LIKE', "%{$value}%"); }); }); }); $users = QueryBuilder::for(User::class) ->defaultSort('name') ->allowedSorts(['name', 'email', 'language_code']) ->allowedFilters(['name', 'email', 'language_code', $globalSearch]) ->paginate() ->withQueryString(); return Inertia::render('Users/Index', [ 'users' => $users, ])->table(function (InertiaTable $table) { $table ->withGlobalSearch() ->defaultSort('name') ->column(key: 'name', searchable: true, sortable: true, canBeHidden: false) ->column(key: 'email', searchable: true, sortable: true) ->column(key: 'language_code', label: 'Language') ->column(label: 'Actions') ->selectFilter(key: 'language_code', label: 'Language', options: [ 'en' => 'English', 'nl' => 'Dutch', ]); } }
客户端安装(Inertia)
您可以通过 npm
或 yarn
安装此包
npm install @starfolksoftware/inertia-table --save yarn add @starfolksoftware/inertia-table
将存储库路径添加到您的 Tailwind 配置文件 中的 content
数组。这确保了样式在生产构建中也有效。
module.exports = { content: [ './node_modules/@starfolksoftware/inertia-table/**/*.{js,vue}', ] }
表格组件
要使用 Table
组件及其所有相关功能,您必须导入 Table
组件并将 users
数据传递给组件。
<script setup> import { Table } from "@starfolksoftware/inertia-table"; defineProps(["users"]) </script> <template> <Table :resource="users" /> </template>
自动检测数据和相关分页元数据的 resource
属性。您也可以通过 data
和 meta
属性手动传递此属性到组件中。
<template> <Table :data="users.data" :meta="users.meta" /> </template>
如果您想手动渲染表格,例如在本包的 v1 中,您可以使用 head
和 body
插槽。此外,您仍然可以使用 meta
属性来渲染分页器。
<template> <Table :meta="users"> <template #head> <tr> <th>User</th> </tr> </template> <template #body> <tr v-for="(user, key) in users.data" :key="key" > <td>{{ user.name }}</td> </tr> </template> </Table> </template>
Table
还有一些额外的属性来调整其前端行为。
<template> <Table :striped="true" :prevent-overlapping-requests="false" :input-debounce-ms="1000" :preserve-scroll="true" /> </template>
自定义列单元格
当使用 auto-fill 时,您可能希望在保持其他列不变的情况下,转换特定列显示的数据。为此,您可以使用单元格模板。以下示例取自上面的 示例控制器。
<template> <Table :resource="users"> <template #cell(actions)="{ item: user }"> <a :href="`/users/${user.id}/edit`"> Edit </a> </template> </Table> </template>
每页多个表格
您可能想在每页使用多个表格组件。显示数据很简单,但使用如过滤、排序和分页等特性需要稍微不同的设置。例如,默认情况下,使用 page
查询键进行数据集分页,但现在您想为每个表格使用不同的键。幸运的是,这个包处理了这个问题,并提供了一个辅助方法来支持 Spatie 的查询包。要使其工作,您需要为表格 命名。
让我们看看 Spatie 的 QueryBuilder
。在这个示例中,有一个公司表格和一个用户表格。我们相应地命名这些表格。首先,调用静态 updateQueryBuilderParameters
方法来告诉包使用不同的查询参数集。现在,filter
变为 companies_filter
,column
变为 companies_column
等。其次,更改数据库分页器的 pageName
。
InertiaTable::updateQueryBuilderParameters('companies'); $companies = QueryBuilder::for(Company::query()) ->defaultSort('name') ->allowedSorts(['name', 'email']) ->allowedFilters(['name', 'email']) ->paginate(pageName: 'companiesPage') ->withQueryString(); InertiaTable::updateQueryBuilderParameters('users'); $users = QueryBuilder::for(User::query()) ->defaultSort('name') ->allowedSorts(['name', 'email']) ->allowedFilters(['name', 'email']) ->paginate(pageName: 'usersPage') ->withQueryString();
然后,我们需要将这些更改应用到 InertiaTable
类。有一个 name
和 pageName
方法可以做到这一点。
return Inertia::render('TwoTables', [ 'companies' => $companies, 'users' => $users, ])->table(function (InertiaTable $inertiaTable) { $inertiaTable ->name('users') ->pageName('usersPage') ->defaultSort('name') ->column(key: 'name', searchable: true) ->column(key: 'email', searchable: true); })->table(function (InertiaTable $inertiaTable) { $inertiaTable ->name('companies') ->pageName('companiesPage') ->defaultSort('name') ->column(key: 'name', searchable: true) ->column(key: 'address', searchable: true); });
最后,将正确的 name
属性传递到 Vue 模板中的每个表格。可选地,您可以设置 preserve-scroll
属性为 table-top
。这确保在新的数据时滚动到表格的顶部。例如,当更改 第二个 表格的页面时,您希望滚动到表格的顶部,而不是页面的顶部。
<script setup> import { Table } from "@starfolksoftware/inertia-table"; defineProps(["companies", "users"]) </script> <template> <Table :resource="companies" name="companies" preserve-scroll="table-top" /> <Table :resource="users" name="users" preserve-scroll="table-top" /> </template>
分页翻译
您可以使用 setTranslations
方法覆盖默认的分页翻译。您可以在主 JavaScript 文件中这样做。
import { setTranslations } from "@starfolksoftware/inertia-table"; setTranslations({ next: "Next", no_results_found: "No results found", of: "of", per_page: "per page", previous: "Previous", results: "results", to: "to" });
Table.vue 插槽
Table.vue
有几个插槽,您可以使用它们来注入自己的实现。
每个插槽都提供了与父 Table
组件交互的 props。
<template> <Table> <template v-slot:tableGlobalSearch="slotProps"> <input placeholder="Custom Global Search Component..." @input="slotProps.onChange($event.target.value)" /> </template> </Table> </template>
测试
在 app
目录中可以找到一个巨大的 Laravel Dusk E2E 测试套件。在这里您会找到一个 Laravel + Inertia 应用程序。
cd app
cp .env.example .env
composer install
npm install
npm run production
touch database/database.sqlite
php artisan migrate:fresh --seed
php artisan dusk:chrome-driver
php artisan serve
php artisan dusk
从 v1 升级
服务器端
- 已将
addColumn
方法重命名为column
。 - 已将
addFilter
方法重命名为selectFilter
。 - 已将
addSearch
方法重命名为searchInput
。 - 对于所有重命名的方法,请检查参数,因为一些已经更改。
- 已删除
addColumns
和addSearchRows
方法。 - 全局搜索现在默认不再启用。
客户端
- 已删除
InteractsWithQueryBuilder
混合,不再需要。 Table
组件不再需要filters
、search
、columns
和on-update
属性。- 当使用自定义的
thead
或tbody
插槽时,您需要手动提供 样式。 - 当使用自定义
thead
时,showColumn
方法已被重命名为show
。 setTranslations
方法不再是Pagination
组件的一部分,但需要导入。- 组件的模板和逻辑不再分离。使用插槽来注入您的自定义实现。
v2.1 路线图
- 布尔过滤器
- 日期过滤器
- 日期范围过滤器
- 将演示应用切换到 Vite
变更日志
有关最近更改的更多信息,请参阅 变更日志。
贡献
有关详细信息,请参阅 贡献指南。
安全
如果您发现任何与安全相关的问题,请通过电子邮件 faruk@starfolksoftware.com 联系我们,而不是使用问题跟踪器。
鸣谢
许可证
MIT 许可证 (MIT)。有关更多信息,请参阅 许可证文件。