v-e-y/datatables-livewire

Laravel, Livewire, Bootstrap 和 Alpine JS

v2.0.11-alpha 2024-05-12 07:43 UTC

README

php artisan vendor:publish --provider="VEY\DataTablesLivewire\DataTablesLivewireServiceProvider"

此包是从以下项目分叉而来 - https://github.com/MedicOneSystems/livewire-datatables

其他致谢和影响

分叉包的“非实际”描述

即将更新

Latest Version on Packagist Total Downloads

功能

  • 使用模型或查询构建器提供数据
  • 使用预设或自定义回调修改和格式化列
  • 使用列或计算列排序数据
  • 使用布尔值、时间、日期、选择或自由文本进行过滤
  • 使用复杂查询构建器创建复杂的组合过滤
  • 显示/隐藏列
  • 列组
  • 支持批量操作

演示应用程序仓库

screenshot

要求

安装

您可以通过 composer 安装此包

composer require mediconesystems/livewire-datatables

如果您使用 Laravel 9,请首先执行

composer require psr/simple-cache:^1.0 maatwebsite/excel

可选

您不必这样做,但如果您愿意,可以发布配置文件和 blade 模板资产

php artisan vendor:publish --provider="Mediconesystems\LivewireDatatables\LivewireDatatablesServiceProvider"

这将使您能够修改 blade 视图并应用自己的样式,datatables 视图将发布到 resources/livewire/datatables。配置文件包含整个应用程序中使用的默认时间和日期格式

  • 如果您在项目中使用 Purge CSS,这将很有用,以确保包含所有 livewire-datatables 类

一些内置的动态组件使用 Alpine JS,因此为了在页面加载时去除闪烁,请确保您在 CSS 中有

[x-cloak] {
    display: none;
}

某个地方

基本用法

  • 在 blade 视图中使用 livewire-datatable 组件,并传入一个模型
...

<livewire:datatable model="App\User" name="all-users" />

...

模板语法

  • 有多种方法可以通过传递额外的属性到组件中修改表格
<livewire:datatable
    model="App\User"
    name="users"
    include="id, name, dob, created_at"
    dates="dob"
/>

注意:请注意,在同一个页面上有多个数据表或在不同页面上有多个同一类型的数据表需要为每个数据表分配一个唯一的 name 属性,以免相互冲突,如上面的示例所示。

属性

组件语法

创建一个扩展 Mediconesystems\LivewireDatatables\LivewireDatatable 的 livewire 组件

php artisan make:livewire-datatable foo --> 'app/Http/Livewire/Foo.php'

php artisan make:livewire-datatable tables.bar --> 'app/Http/Livewire/Tables/Bar.php'

通过声明公共属性 $model 公共方法 builder() 返回 Illuminate\Database\Eloquent\Builder 实例来提供数据源

php artisan make:livewire-datatable users-table --model=user --> 'app/Http/Livewire/UsersTable.php' with public $model = User::class

声明一个公共方法 columns 返回一个包含一个或多个 Mediconesystems\LivewireDatatables\Column 的数组

可以使用以下任何静态方法构建列,然后使用流畅的方法链分配其属性。还有额外的特定类型的 Column; NumberColumnDateColumnTimeColumn,使用正确的类型将启用特定类型的格式化和过滤

class ComplexDemoTable extends LivewireDatatable
{

    public function builder()
    {
        return User::query();
    }

    public function columns()
    {
        return [
            NumberColumn::name('id')
                ->label('ID')
                ->linkTo('job', 6),

            BooleanColumn::name('email_verified_at')
                ->label('Email Verified')
                ->format()
                ->filterable(),

            Column::name('name')
                ->defaultSort('asc')
                ->group('group1')
                ->searchable()
                ->hideable()
                ->filterable(),

            Column::name('planet.name')
                ->label('Planet')
                ->group('group1')
                ->searchable()
                ->hideable()
                ->filterable($this->planets),

            // Column that counts every line from 1 upwards, independent of content
            Column::index($this);

            DateColumn::name('dob')
                ->label('DOB')
                ->group('group2')
                ->filterable()
                ->hide(),

            (new LabelColumn())
                ->label('My custom heading')
                ->content('This fixed string appears in every row'),

            NumberColumn::name('dollars_spent')
                ->enableSummary(),
        ];
    }
}

列方法

监听器

组件将监听 refreshLivewireDatatable 事件,允许您从外部组件刷新表格。

Eloquent 列名称

可以使用 Eloquent 点表示法包含 Eloquent 关系中的列,例如 planet.name,Livewire Datatables 将自动添加必要的表连接来包含该列。如果关系是 'many' 类型(HasManyBelongsToManyHasManyThrough),则 Livewire Datatables 将创建一个聚合子查询(这比连接和分组更有效率。感谢 @reinink)。默认情况下,聚合类型将是对数值列的 count 和对字符串列的 group_concat,但可以使用冒号分隔符来覆盖。

NumberColumn::name('students.age:sum')->label('Student Sum'),

NumberColumn::name('students.age:avg')->label('Student Avg'),

NumberColumn::name('students.age:min')->label('Student Min'),

NumberColumn::name('students.age:max')->label('Student Max'),

列组

当您有一个非常大的表格和很多列时,您可以创建 '列组',允许用户一次性切换整个组的可见性。在任何列上使用 ->group('NAME') 来实现这一点。您可以通过表格的 groupLabels 属性为您的组提供可读标签和翻译。

class GroupDemoTable extends LivewireDatatable
{
    public $groupLabels = [
         'group1' => 'app.translation_for_group_1'
         'group2' => 'app.translation_for_group_2'
    ];

public function columns()
{
    return [
        Column::name('planets.name')
            ->group('group1')
            ->label('Planet'),

        Column::name('planets.name')
            ->group('group2')
            ->label('Planet'),

汇总行

如果您需要汇总特定列的所有单元格,可以使用 enableSummary()

public function columns()
{
    return [
        Column::name('dollars_spent')
            ->label('Expenses in Dollar')
            ->enableSummary(),

        Column::name('euro_spent')
            ->label('Expenses in Euro')
            ->enableSummary(),

批量操作

如果您想要一次性对多个记录进行操作,您可以在您的表格中使用 buildActions() 方法。

public function buildActions()
    {
        return [

            Action::value('edit')->label('Edit Selected')->group('Default Options')->callback(function ($mode, $items) {
                // $items contains an array with the primary keys of the selected items
            }),

            Action::value('update')->label('Update Selected')->group('Default Options')->callback(function ($mode, $items) {
                // $items contains an array with the primary keys of the selected items
            }),

            Action::groupBy('Export Options', function () {
                return [
                    Action::value('csv')->label('Export CSV')->export('SalesOrders.csv'),
                    Action::value('html')->label('Export HTML')->export('SalesOrders.html'),
                    Action::value('xlsx')->label('Export XLSX')->export('SalesOrders.xlsx')->styles($this->exportStyles)->widths($this->exportWidths)
                ];
            }),
        ];
    }

批量操作样式

如果您只需要对批量操作下拉菜单进行小的样式调整,您可以在这里调整一些设置。

public function getExportStylesProperty()
    {
        return [
            '1'  => ['font' => ['bold' => true]],
            'B2' => ['font' => ['italic' => true]],
            'C'  => ['font' => ['size' => 16]],
        ];
    }

    public function getExportWidthsProperty()
    {
        return [
            'A' => 55,
            'B' => 45,
        ];
    }

固定记录

如果您想允许用户将特定的记录固定以便进行比较等,您可以使用 CanPinRecords 特性。确保至少有一个复选框列,以便用户可以选择记录。

use Mediconesystems\LivewireDatatables\Traits\CanPinRecords;

class RecordTable extends LivewireDatatable
{
    use CanPinRecords;

    public $model = Record::class;

    public function columns()
    {
        return [
            Column::checkbox(),

            // ...

自定义列名称

您仍然可以完全控制您的表格,您可以使用任何查询定义 builder 方法,使用您自己的连接、分组等,然后使用标准的 SQL 语法命名您的列。

public function builder()
{
    return User::query()
        ->leftJoin('planets', 'planets.id', 'users.planet_id')
        ->leftJoin('moons', 'moons.id', 'planets.moon_id')
        ->groupBy('users.id');
}

public function columns()
{
    return [
        NumberColumn::name('id')
            ->filterable(),

        Column::name('planets.name')
            ->label('Planet'),

        Column::raw('GROUP_CONCAT(planets.name SEPARATOR " | ") AS `Moon`'),

        ...
}

回调函数

回调函数让您在显示到表格之前对数据进行任何所需的更改。

  • 回调函数是在数据库查询的分页结果上执行的,因此不应该使用太多内存。
  • 回调函数将接收选定的列作为其参数。
  • 回调函数可以像下面这样定义,或者作为 Datatable 类的公共方法,通过将名称作为字符串传递给回调方法的第二个参数来引用。
  • 如果您想为导出格式化结果,请使用 ->exportCallback(Closure $callback)
class CallbackDemoTable extends LivewireDatatable
{
    public model = User::class

    public function columns()
    {
        return [
            Column::name('users.id'),

            Column::name('users.dob')->format(),

            Column::callback(['dob', 'signup_date'], function ($dob, $signupDate) {
                $age = $signupDate->diffInYears($dob);
                return $age > 18
                    ? '<span class="text-red-500">' . $age . '</span>'
                    : $age;
            })->exportCallback(function ($dob, $signupDate), {
                return $age = $signupDate->diffInYears($dob);
            }),

            ...
    }
}

默认过滤器

如果您想在您的表格上应用默认过滤器,您可以使用 defaultFilters 属性。默认过滤器应该是一个包含列名称和要使用的默认过滤器值的数组。当有持久化的过滤器($this->persistFilters 为 true 且有可用会话值)时,它将覆盖默认过滤器。

在下面的示例中,表格将默认过滤掉 deleted_at 列为 false 的行。如果用户有 deleted_at 列的持久化过滤器,则默认过滤器将被忽略。

class CallbackDemoTable extends LivewireDatatable
{
    public $defaultFilters = [
        'deleted_at' => '0',
    ];

    public function builder()
    {
        return User::query()->withTrashed();
    }

    public function columns()
    {
        return [
            Column::name('id'),
            BooleanColumn::name('deleted_at')->filterable(),
        ];
    }
}

视图

您可以将列的输出直接管道到单独的 blade 视图模板中。

  • 模板使用常见的 Laravel 视图辅助语法指定。
  • 视图将接收列的值作为 $value,以及整个查询行作为 $row
class CallbackDemoTable extends LivewireDatatable
{
    public model = User::class

    public function columns()
    {
        return [
            Column::name('users.id'),

            Column::name('users.dob')->view('tables.dateview'),

            Column::name('users.signup_date')->format(),
        ];
    }
'tables/dateview.blade.php'
<span class="mx-4 my-2 bg-pink-500">
    <x-date-thing :value="$value" />
</span>

可编辑列

您可以使用 editable 标记列。这使用上面的 view() 方法将数据传递到可以直接更新底层数据库数据的 Alpine/Livewire 组件。要求列使用标准的 Laravel 命名定义 column。这只是一个示例。可以通过上面的回调或视图方法构建更全面的自定义可编辑列,包括验证等。

class EditableTable extends LivewireDatatable
{

    public $model = User::class;

    public function columns()
    {
        return [
            Column::name('id')
                ->label('ID')
                ->linkTo('job', 6),

            Column::name('email')
                ->editable(),

            ...
        ];
    }
}

复杂查询构建器

只需在您的 Datatable 类中添加 $complex = true,所有可筛选的列都将可用在复杂查询构建器中。

功能

  • 使用 AND/OR 逻辑组合规则和规则组
  • 在界面中拖放规则

image

持久化查询(需要 AlpineJS v3 和 $persist 插件)

  • $persistComplexQuery = true 添加到您的类中,查询将存储在浏览器本地存储中。
  • 默认情况下,本地存储的键将是类名。您可以通过设置公共属性 $persistKey 或在 Datatable 类上重写 getPersistKeyProperty() 来提供自己的键
  • 例如:对于用户特定的持久化
public function getPersistKeyProperty()
{
    return Auth::id() . '-' . parent::getPersistKeyProperty();
}

保存查询

如果您想永久保存查询,您必须提供 3 个方法来添加、删除和检索您的保存的查询,使用您喜欢的任何逻辑

  • public function saveQuery(String $name, Array $rules)
  • public function deleteQuery(Int $id)
  • public function getSavedQueries()
  • 在您的保存和删除方法中,确保发出 updateSavedQueries livewire 事件,并传递一个新的结果数组(见以下示例)

示例

此示例显示使用传统 Laravel ComplexQuery 模型保存查询,该模型属于 User

/* Migration */

class CreateComplexQueriesTable extends Migration
{
    public function up()
    {
        Schema::create('complex_queries', function (Blueprint $table) {
            $table->id();
            $table->unsignedInteger('user_id');
            $table->string('table');
            $table->json('rules');
            $table->string('name');
            $table->timestamps();
        });
    }
}


/* Model */

class ComplexQuery extends BaseModel
{
    protected $casts = ['rules' => 'array'];

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

/* Datatable Class */

class TableWithSaving extends LivewireDatatable
{
    ...

    public function saveQuery($name, $rules)
    {
        Auth::user()->complex_queries()->create([
            'table' => $this->name,
            'name' => $name,
            'rules' => $rules
        ]);

        $this->emit('updateSavedQueries', $this->getSavedQueries());
    }

    public function deleteQuery($id)
    {
        ComplexQuery::destroy($id);

        $this->emit('updateSavedQueries', $this->getSavedQueries());
    }

    public function getSavedQueries()
    {
        return Auth::user()->complex_queries()->where('table', $this->name)->get();
    }

    ...
}

样式

我知道提供带有大量有偏见的标记和样式的包并不酷。其他大多数包似乎都走上了通过将可选类作为参数或配置变量传递的道路。我的观点是,因为这是 blade 与 tailwind,您可以发布模板,并对它们做任何您想做的事情 - 应该很明显 Livewire 和 Alpine 的移动部分在哪里。

有方法可以应用于行和单元格的样式。 rowClasses 接收 $rowlaravel 循环变量 作为参数。 cellClasses 接收 $row$column

例如

public function rowClasses($row, $loop)
{
    return 'divide-x divide-gray-100 text-sm text-gray-900 ' . ($this->rowIsSelected($row) ? 'bg-yellow-100' : ($row->{'car.model'} === 'Ferrari' ? 'bg-red-500' : ($loop->even ? 'bg-gray-100' : 'bg-gray-50')));
}

public function cellClasses($row, $column)
{
    return 'text-sm ' . ($this->rowIsSelected($row) ? ' text-gray-900' : ($row->{'car.model'} === 'Ferrari' ? ' text-white' : ' text-gray-900'));
}

您可以通过更改 livewire-datatables.php 配置文件中的 default_classes 来更改 rowClassescellClasses 方法应用的默认 CSS 类。

您还可以在表格的类中重写 render 方法,为不同的表格提供不同的模板。

致谢和影响