fontech / nova-repeatable-fields
一个 Laravel Nova 字段。
Requires
- php: >=7.1.0
README
注意
强烈建议您使用 Nova 可变内容包而不是这个包
Nova 可变内容包正在积极维护,允许您将任何有效的 Nova 字段用作子字段。由于其他承诺,这个包只偶尔维护,不太可能添加新功能,因此新用户应强烈考虑使用 Nova 可变内容包而不是这个包。
希望迁移到 Nova 可变内容包的此包现有用户需要做一些工作来迁移数据。请参阅下面的附录,其中提供了一个迁移数据的潜在解决方案。
Nova 应用程序的重复字段
这个包包含一个 Laravel Nova 字段,可以创建重复的“子”字段集合。Nova 用户可以自由创建、重新排序和删除多个具有您定义的子字段的数据行。数据以 JSON 格式保存到数据库中。
示例
安装
您可以通过 composer 将此包安装到使用 Nova 的 Laravel 应用程序中
composer require fourstacks/nova-repeatable-fields
用法
要添加重复字段,请在您的 Nova 资源中使用 Fontech\NovaRepeatableFields\Repeater
字段
namespace App\Nova; use Fontech\NovaRepeatableFields\Repeater; // ... class Petstore extends Resource { // ... public function fields(Request $request) { return [ // ... Repeater::make('Dogs'), // ... ]; } }
为了使用此包,您还应该确保您的 Nova 资源所代表的 Eloquent 模型将您希望用作重复字段的属性转换为数组
namespace App; // ... class Petstore extends Model { protected $casts = [ 'dogs' => 'array' ] }
底层数据库字段应该是 string
或 text
类型字段。
配置
此包包含各种选项,您可以使用这些选项定义重复字段内的子字段
addField
参数:array
您创建的每个重复字段都应该包含至少一个通过 addField
添加的子字段。addField
方法接受一个子字段配置选项数组
Repeater::make('Dogs') ->addField([ // configuation options ])
配置选项包括
label
[ 'label' => 'Dog name', //... ]
所有子字段至少必须使用一个“label”进行定义。这是一个可读性强的字符串,将出现在 Nova UI 中。
name
[ 'name' => 'dog_name', //... ]
默认情况下,子字段的 name
(用于在数据库中保存数据)将自动使用子字段 label
的蛇形版本生成。或者,您也可以自由覆盖此约定并定义一个自定义名称。
type
[ 'type' => 'number', //... ]
默认情况下,子字段的输入类型将是一个标准的文本字段。如果您愿意,可以定义不同的字段类型。目前支持的子字段类型有:'text'、'number'、'select'、'textarea'。
placeholder
[ 'placeholder' => 'Name that dog', //... ]
默认情况下,输入的 placeholder
将与子字段的 label
相同。但是,您可以使用此选项定义一个自定义占位符,该占位符将代替它出现。
width
[ 'width' => 'w-1/2', //... ]
如果您选择以行形式显示您的子字段(而不是堆叠 - 请参阅下面的 displayStackedForm
选项),则可以使用 Tailwind 的分数宽度类 定义您的字段宽度。除非您想这样做,否则不需要为所有字段定义宽度。如果任何子字段没有输入宽度,则所有子字段都将具有相同的宽度。
请注意,您可以混合和匹配宽度。例如,您可能希望将前两个字段设置为 50% 宽度,使用 w-1/2
,然后将最后一个字段设置为全宽度,通过 w-full
。
如果您以堆叠布局显示子字段,则宽度选项将不起作用。
选项
[ 'options' => [ 'fido' => 'Fido', 'mr_bubbles' => 'Mr Bubbles', 'preston' => 'Preston' ], //... ]
如果您正在定义的子字段的 type
是 'select',您需要定义一个选项数组供选择字段使用。这些通过键/值对数组定义。
属性
[ 'attributes' => [ 'min' => 1, 'max' => '20', 'style' => 'color: red' ], //... ]
通过 attributes
键,您可以自由地定义任何您希望通过关联数组添加到输入的自定义属性。这些将通过 v-bind
添加。例如,您可能希望向数字字段添加最小或最大步骤,或向文本字段添加样式属性。
addButtonText
Repeater::make('Dogs') ->addButtonText('Add new dog');
您可以配置用于在 Nova UI 中添加新子字段集的按钮文本。默认情况下,此按钮标记为 '添加行',但您可以使用 addButtonText
选项来覆盖此内容。
summaryLabel
Repeater::make('Dogs') ->summaryLabel('Dogs');
详细视图和索引视图显示通过重复字段输入的数据摘要。默认情况下,这将显示行数,例如 '3 行',以及一个链接以展开显示输入的完整数据。
您可以覆盖此摘要文本为更具体的内容,例如 '3 只狗'。
displayStackedForm
Repeater::make('Dogs') ->displayStackedForm();
默认情况下,一组子字段将作为一系列水平对齐的输入字段显示。
这对于只有 2 或 3 个子字段的重复字段效果很好,但对于更大的字段集,堆叠布局(显示子字段上下排列)通常是一个更易用的布局。您可以使用此选项切换到堆叠布局。
initialRows
Repeater::make('Dogs') ->initialRows(4);
设置在表单初始化时预添加的初始行数。对于具有现有行的表单,它将添加多达设置数量的行。
maximumRows
Repeater::make('Dogs') ->maximumRows(4);
设置行数的最大上限。达到此限制后,您将无法添加新行。
heading
Repeater::make('Dogs') ->heading('Dog');
设置每行之间的标题(例如,狗 #1、狗 #2)。仅在与 "displayStackedForm" 一起使用时才有效。
附录 - 将数据迁移到 Nova 可灵活内容
本指南仅适用于希望使用 Nova 可灵活内容包并希望了解如何迁移数据的现有用户。
请注意,以下解决方案仅为指南。您必须实现并测试适合您数据的具体解决方案,并且在运行可能更改多个数据库行的代码之前,强烈建议您备份任何数据。
我对于您使用以下代码对现有数据所做的任何更改不承担责任。明白了?好的,让我们继续...
本指南假定您已经 安装了 Nova 可灵活内容包,并且您已经 为要迁移的数据设置了布局。
接下来,在您的应用程序中创建一个新的 artisan 命令: php artisan make:command MigrateRepeaterData
添加以下代码,以便您的命令看起来像这样
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Schema; class MigrateRepeaterData extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'nfc:migrate'; /** * The console command description. * * @var string */ protected $description = 'Migrate your repeater data to be compatible with Nova Flexible Content'; /** * Execute the console command. * * @return mixed */ public function handle() { // Get the model to run this command for $model = $this->ask('Which model do you want to migrate data for? Enter the full namespace e.g. App\Post'); if(! class_exists($model)){ $this->error("Sorry - could not find a model called {$model}"); return; } // Get the attribute on the model that holds the old repeater data $attribute = $this->ask('Which model attribute holds the data you want to migrate?'); if(! Schema::hasColumn((new $model)->getTable(), $attribute) ){ $this->error("Sorry - could not find a database column called {$attribute} for {$model}"); return; } // Get the Nova Flexible Content layout name $layout = $this->ask('What is the name of the Nova Flexible Content layout for this data?'); $models = $model::all(); if ($this->confirm("About to migrate data for {$models->count()} models. Do you wish to continue?")) { $models->each(function($model) use ($attribute, $layout){ $model->$attribute = $this->updateValues($model->$attribute, $layout); $model->save(); }); $this->info('All done! Please check your data to ensure it was migrated correctly'); } } protected function updateValues($data, $layout) { // Skip anything that is not an array with elements and keep the value the same if(! $data){ return $data; } return collect($data) ->map(function($attributes) use ($layout){ return [ // Create a random key 'key' => $this->generateKey(), // my_nova_flexible_content_layout should match the name // you gave to your Nova Flexible Content layout 'layout' => $layout, // The data for a given repeater 'row' 'attributes' => $attributes ]; }) ->all(); } protected function generateKey() { if (function_exists("random_bytes")) { $bytes = random_bytes(ceil(16/2)); } elseif (function_exists("openssl_random_pseudo_bytes")) { $bytes = openssl_random_pseudo_bytes(ceil(16/2)); } else { throw new \Exception("No cryptographically secure random function available"); } return substr(bin2hex($bytes), 0, 16); } }
更新日志
有关最近更改的更多信息,请参阅 更新日志。
致谢
许可协议
MIT 许可协议(MIT)。有关更多信息,请参阅 许可文件。