在 Blade 视图中渲染表单
WARNING
继续之前,请确认项目中已安装 filament/forms。可通过运行以下命令检查:
composer show filament/forms若尚未安装,请参阅安装指南,并按说明配置独立组件。
设置 Livewire 组件
首先,生成一个新的 Livewire 组件:
php artisan make:livewire CreatePost然后,在页面上渲染该 Livewire 组件:
@livewire('create-post')或者,你也可以使用整页 Livewire 组件:
use App\Livewire\CreatePost;
use Illuminate\Support\Facades\Route;
Route::get('posts/create', CreatePost::class);添加表单
WARNING
继续之前,请确保项目中已安装 Forms 包。请参阅安装指南,并按说明配置独立组件。
向 Livewire 组件类添加表单时有 5 项主要任务,每一项都很关键:
- 实现 `HasSchemas` 接口并使用 `InteractsWithSchemas` trait。
- 定义一个公共 Livewire 属性来存储表单数据。本例中我们称之为 `$data`,你也可以使用任意名称。
- 添加 `form()` 方法,在此配置表单。[添加表单的 schema](/5.x/forms/overview#form-schemas),并告诉 Filament 将表单数据存储在 `$data` 属性中(使用 `statePath('data')`)。
- 在 `mount()` 中用 `$this->form->fill()` 初始化表单。你构建的每个表单都必须这样做,即使没有任何初始数据。
- 定义一个处理表单提交的方法。本例中我们称之为 `create()`,你也可以使用任意名称。在该方法中,可用 `$this->form->getState()` 验证并获取表单数据。务必使用此方法,而不是直接访问 `$this->data` 属性,因为表单数据需要先验证并转换为有用格式再返回。
<?php
namespace App\Livewire;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Concerns\InteractsWithSchemas;
use Filament\Schemas\Concerns\RestrictsFileUploadsToSchemaComponents;
use Filament\Schemas\Contracts\HasSchemas;
use Illuminate\Contracts\View\View;
use Filament\Schemas\Schema;
use Livewire\Component;
class CreatePost extends Component implements HasSchemas
{
use InteractsWithSchemas;
use RestrictsFileUploadsToSchemaComponents;
public ?array $data = [];
public function mount(): void
{
$this->form->fill();
}
public function form(Schema $schema): Schema
{
return $schema
->components([
TextInput::make('title')
->required(),
MarkdownEditor::make('content'),
// ...
])
->statePath('data');
}
public function create(): void
{
dd($this->form->getState());
}
public function render(): View
{
return view('livewire.create-post');
}
}最后,在 Livewire 组件的视图中渲染表单:
<div>
<form wire:submit="create">
{{ $this->form }}
<button type="submit">
Submit
</button>
</form>
<x-filament-actions::modals />
</div>INFO
<x-filament-actions::modals /> 用于渲染表单组件的操作模态框。该代码可放在 <form> 元素外的任意位置,只要仍在 Livewire 组件内即可。
在浏览器中访问你的 Livewire 组件,应该能看到 components() 中的表单组件:
提交带数据的表单后,你会看到表单数据被 dump 到屏幕上。你也可以将数据保存到模型,而不是 dump:
use App\Models\Post;
public function create(): void
{
Post::create($this->form->getState());
}INFO
filament/forms 还包含以下包:
filament/actionsfilament/schemasfilament/support
这些包允许你在 Livewire 组件中使用它们的组件。 例如,若你的表单使用了 Actions,请记得在 Livewire 组件类上实现 HasActions 接口并使用 InteractsWithActions trait。
若在表单中使用了其他 Filament 组件,请务必一并安装并集成对应的包。
用数据初始化表单
要用数据填充表单,只需将该数据传给 $this->form->fill() 方法。例如,若正在编辑已有帖子,可以这样做:
use App\Models\Post;
public function mount(Post $post): void
{
$this->form->fill($post->attributesToArray());
}务必使用 $this->form->fill() 方法,而不是直接将数据赋给 $this->data 属性。因为帖子数据需要在内部转换为有用格式后再存储。
WARNING
传给 fill() 的数据会作为 Livewire 请求的一部分暴露给 JavaScript。若模型中有包含非有效 UTF-8 二进制数据的列,例如 geometry、point 或 blob 列,则无法序列化为 JSON,页面会加载失败,通常表现为空白屏,且 Laravel 日志中没有错误。
要解决此问题,请将该列加入模型的 $hidden 数组,使其从 attributesToArray() 中排除:
protected $hidden = ['location'];设置表单模型
让 $form 能访问模型有几个好处:
- 允许表单中的字段从该模型加载信息。例如,select 字段可以自动[从数据库加载选项](/5.x/forms/select#integrating-with-an-eloquent-relationship)。
- 表单可以自动加载并保存模型的关系数据。例如,你有一个 Edit Post 表单,其中有一个管理该帖子关联评论的 [Repeater](/5.x/forms/repeater#integrating-with-an-eloquent-relationship)。当你调用 `$this->form->fill([...])` 时,Filament 会自动加载该帖子的评论;调用 `$this->form->getState()` 时会将它们保存回关系。
- 像 `exists()` 和 `unique()` 这样的验证规则可以自动从模型获取数据库表名。
建议在有模型时始终将其传给表单。如前所述,这会解锁 Filament 表单系统的许多新能力。
要将模型传给表单,请使用 $form->model() 方法:
use Filament\Schemas\Schema;
public Post $post;
public function form(Schema $schema): Schema
{
return $schema
->components([
// ...
])
->statePath('data')
->model($this->post);
}在表单提交后传入表单模型
在某些情况下,表单的模型要到表单提交后才可用。例如,在 Create Post 表单中,帖子直到表单提交后才存在。因此,你无法将其传入 $form->model()。不过,你可以改为传入模型类:
use App\Models\Post;
use Filament\Schemas\Schema;
public function form(Schema $schema): Schema
{
return $schema
->components([
// ...
])
->statePath('data')
->model(Post::class);
}单独这样做不如传入模型实例强大。例如,创建帖子后关系不会被保存。为此,需要在创建帖子后将其传给表单,并调用 saveRelationships() 将关系保存到它:
use App\Models\Post;
public function create(): void
{
$post = Post::create($this->form->getState());
// Save the relationships from the form to the post after it is created.
$this->form->model($post)->saveRelationships();
}将表单数据保存到单独属性
在之前的所有示例中,我们将表单数据保存到 Livewire 组件上的公共 $data 属性。不过,你也可以将数据保存到单独属性。例如,若表单有 title 字段,可将表单数据保存到 $title 属性。为此,完全不要向表单传入 statePath()。确保所有字段在类上都有各自的公共属性。
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Schema;
public ?string $title = null;
public ?string $content = null;
public function form(Schema $schema): Schema
{
return $schema
->components([
TextInput::make('title')
->required(),
MarkdownEditor::make('content'),
// ...
]);
}使用多个表单
可使用 InteractsWithSchemas trait 定义多个表单。每个表单应使用同名方法:
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Schema;
public ?array $postData = [];
public ?array $commentData = [];
public function editPostForm(Schema $schema): Schema
{
return $schema
->components([
TextInput::make('title')
->required(),
MarkdownEditor::make('content'),
// ...
])
->statePath('postData')
->model($this->post);
}
public function createCommentForm(Schema $schema): Schema
{
return $schema
->components([
TextInput::make('name')
->required(),
TextInput::make('email')
->email()
->required(),
MarkdownEditor::make('content')
->required(),
// ...
])
->statePath('commentData')
->model(Comment::class);
}现在,每个表单可通过其名称而不是 form 来访问。例如,要填充帖子表单,可使用 $this->editPostForm->fill([...]);要从评论表单获取数据,可使用 $this->createCommentForm->getState()。
你会注意到每个表单都有自己唯一的 statePath()。每个表单会将状态写入 Livewire 组件上的不同数组,因此本例中必须定义公共属性 $postData 和 $commentData。
重置表单数据
可随时调用 $this->form->fill() 将表单重置为默认数据。例如,你可能希望每次提交后清空表单内容:
use App\Models\Comment;
public function createComment(): void
{
Comment::create($this->form->getState());
// Reinitialize the form to clear its data.
$this->form->fill();
}使用 CLI 生成表单 Livewire 组件
建议先学习如何手动用表单设置 Livewire 组件;熟练后,可使用 CLI 为你生成表单。
php artisan make:filament-livewire-form RegistrationForm这会生成新的 app/Livewire/RegistrationForm.php 组件,你可以自行定制。
为 Eloquent 模型生成表单
Filament 还能为特定 Eloquent 模型生成表单。这类表单更强大,因为它们会自动为你保存表单数据,并确保表单字段正确配置以访问该模型。
使用 make:livewire-form 命令生成表单时,会询问模型名称:
php artisan make:filament-livewire-form Products/CreateProduct为 Eloquent 记录生成编辑表单
默认情况下,向 make:livewire-form 命令传入模型会生成在数据库中创建新记录的表单。若向命令传入 --edit 标志,则会为特定记录生成编辑表单。这会自动用该记录的数据填充表单,并在提交时将数据保存回模型。
php artisan make:filament-livewire-form Products/EditProduct --edit自动生成表单 Schema
Filament 还能根据模型的数据库列猜测你想要的表单字段。生成表单时可使用 --generate 标志:
php artisan make:filament-livewire-form Products/CreateProduct --generate文件上传的安全注意事项
InteractsWithSchemas trait 会在每个使用它的组件上暴露 Livewire 的文件上传 RPC 方法——无论表单是否包含上传字段。若你的 Livewire 组件可被你不希望其上传任意文件的用户访问,请添加 RestrictsFileUploadsToSchemaComponents trait。详情见将 Livewire 文件上传限制到 schema 组件。