protonemedia / inertiajs-tables-laravel-query-builder
Inertia.js 前端组件,用于 Spatie 的 Laravel 查询构建器
Requires
- php: ^8.1|^8.2
- illuminate/support: ^9.37|^10.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
该软件包不再维护,但它有一个继任者:[Inertia Table](https://inertiaui.com/inertia-table) 🚀
Inertia Table 是一个全新的、高端软件包,从头开始构建。它结合了此软件包的最佳功能以及 Splade 变体的所有增强和新功能。此存储库中的软件包被认为是遗留软件,将不再更新。它有一些在新的软件包中得到修复的架构缺陷。
新软件包具有现代基础,并包含许多请求的功能,如 日期过滤器、批量操作、导出、暗黑模式、内置查询构建器 和 更好的定制。还有一个即将推出的 React 版本。请查看新软件包的所有功能,请参阅文档:https://inertiaui.com/inertia-table/docs/introduction
此软件包为 Inertia.js 提供了类似 DataTables 的体验,支持搜索、过滤、排序、切换列和分页。它生成可以被 Spatie 的优秀 Laravel 查询构建器 软件包消费的 URL,无需额外的逻辑。组件使用 Tailwind CSS 3.0 样式化,但可以通过插槽完全自定义。数据刷新逻辑基于 Inertia 的 Ping CRM 示例。
支持此软件包!
❤️ 我们自豪地通过开发 Laravel 软件包并将它们免费提供给社区来支持社区。如果这个软件包为您节省了时间或如果您在专业上依赖它,请考虑 赞助维护和开发。跟踪问题和拉取请求需要时间,但我们很乐意帮助!
特性
- 自动填充:自动生成带有自定义单元格支持的
thead
和tbody
- 全局搜索
- 按字段搜索
- 选择过滤器
- 切换列
- 排序列
- 分页(支持 Eloquent/API Resource/Simple/Cursor)
- 自动更新查询字符串(通过使用 Inertia 的 replace 功能)
兼容性
- Vue 3
- Laravel 9
- Inertia.js
- Tailwind CSS v3 + 表单插件
- PHP 8.0+
注意:目前使用 Vite 与此软件包存在 问题!
安装
您需要安装服务器端软件包和客户端软件包。请注意,此软件包仅与 Laravel 9、Vue 3.0 兼容,并需要 Tailwind Forms 插件。
服务器端安装(Laravel)
您可以通过 composer 安装该软件包
composer require protonemedia/inertiajs-tables-laravel-query-builder
该软件包将自动注册 Service Provider,该 Service Provider 提供一个可以在 Inertia 响应中使用的 table
方法。
搜索字段
使用 searchInput
方法,您可以指定哪些属性可以搜索。搜索查询作为 filter
传递到 URL 查询中。这可以无缝集成到 Laravel 查询构建器包的 过滤功能。
尽管传递列键就足够了,但您也可以指定自定义标签和默认值。
use ProtoneMedia\LaravelQueryBuilderInertiaJs\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', '用户名')
。
全局搜索
您可以使用 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 ProtoneMedia\LaravelQueryBuilderInertiaJs\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 @protonemedia/inertiajs-tables-laravel-query-builder --save yarn add @protonemedia/inertiajs-tables-laravel-query-builder
将存储库路径添加到您的 Tailwind 配置文件 中的 content
数组。这确保了样式在生产构建中也有效。
module.exports = { content: [ './node_modules/@protonemedia/inertiajs-tables-laravel-query-builder/**/*.{js,vue}', ] }
表格组件
要使用 Table
组件及其所有相关功能,您必须导入 Table
组件并将 users
数据传递到组件中。
<script setup> import { Table } from "@protonemedia/inertiajs-tables-laravel-query-builder"; 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>
自定义列单元格
当使用 自动填充 时,您可能希望在不影响其他列的情况下转换特定列呈现的数据。为此,您可以使用单元格模板。此示例取自上面的 示例控制器。
<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); });
最后,在Vue模板中将正确的name
属性传递给每个表格。可选地,您可以将preserve-scroll
属性设置为table-top
。这确保在新数据时滚动到表格的顶部。例如,当更改第二张表的页面时,您希望滚动到表格的顶部,而不是页面的顶部。
<script setup> import { Table } from "@protonemedia/inertiajs-tables-laravel-query-builder"; 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 "@protonemedia/inertiajs-tables-laravel-query-builder"; 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
组件交互的属性。
<template> <Table> <template v-slot:tableGlobalSearch="slotProps"> <input placeholder="Custom Global Search Component..." @input="slotProps.onChange($event.target.value)" /> </template> </Table> </template>
测试
一个巨大的Laravel Dusk端到端测试套件可以在app
目录中找到。在这里,您将找到一个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
变更日志
有关最近更改的更多信息,请参阅CHANGELOG。
贡献
有关详细信息,请参阅CONTRIBUTING。
其他Laravel包
Laravel Analytics Event Tracking
:一个Laravel包,可以轻松地将事件发送到Google Analytics。Laravel Blade On Demand
:一个Laravel包,可以在内存中编译Blade模板。Laravel Cross Eloquent Search
:一个Laravel包,可以在多个Eloquent模型中搜索。Laravel Eloquent Scope as Select
:停止在PHP中重复Eloquent查询范围和约束。此包允许您通过添加子查询来重用查询范围和约束。Laravel Eloquent Where Not
:此Laravel包允许您翻转/反转Eloquent范围或任何查询约束。Laravel FFMpeg
:此包为 Laravel 提供了 FFmpeg 的集成。文件的存储由 Laravel 的文件系统处理。Laravel Form Components
:Blade 组件,可用于快速使用 Tailwind CSS 自定义表单和 Bootstrap 4 构建表单。支持验证、模型绑定、默认值、翻译,包括默认供应商样式和完全可自定义!Laravel Mixins
:Laravel 精选工具集。Laravel Verify New Email
:此包添加了验证新电子邮件地址的支持:当用户更新其电子邮件地址时,在新的电子邮件地址被验证之前,不会替换旧的电子邮件地址。Laravel Paddle
:支持 webhooks/events 的 Laravel 与 paddle.com API 集成。Laravel WebDAV
:Laravel 文件系统的 WebDAV 驱动。
安全性
如果您发现任何安全相关的问题,请通过电子邮件发送给 pascal@protone.media,而不是使用问题跟踪器。
鸣谢
许可证
MIT 许可证(MIT)。更多信息请参阅 许可证文件。