在 Livewire 组件中添加表单
设置 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);
添加表单
添加表单到 Livewire 组件类有 5 个重要步骤:
- 实现
HasForms
接口并使用InteractsWithForms
trait。 - 定义公共 Livewire 属性,来保存表单数据。在我们的例子中,我们把这个属性叫做
$data
,不过你可以根据需要进行命名。 - 添加
form()
方法,这是你配置表单的地方。然后添加表单 Schema,并告诉 Filament 在$data
属性中保存表单数据(使用statePath('data')
)。 - 在
mount()
中调用$this->form->fill()
,初始化表单。这对于每个表单都是必不可少的,即使它没有初始化任何数据。 - 定义一个方法来处理表单提交。在我们的示例中,我们使用
create()
,你也可以自己命名。在该方法内,你可以使用$this->form->getState()
验证和获取表单数据。使用该方法,而不是直接获取$this->data
属性,因为表单数据需要在返回前验证并转换成有效格式。
<?php
namespace App\Livewire;
use App\Models\Post;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Contracts\View\View;
use Livewire\Component;
class CreatePost extends Component implements HasForms
{
use InteractsWithForms;
public ?array $data = [];
public function mount(): void
{
$this->form->fill();
}
public function form(Form $form): Form
{
return $form
->schema([
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>
<x-filament-actions::modals />
用于渲染表单组件 Action 模态框。这段代码可以放在<form>
元素之外的任何地方,只要它还在 Livewire 组件内。
现在到浏览器访问 Livewire 组件,你应该就能看到表单组件了。
将表单数据提交,你将会看到表单数据打印到屏幕中。你可以将这些数据存入模型,而不是打印:
use App\Models\Post;
public function create(): void
{
Post::create($this->form->getState());
}
使用数据初始化表单
要使用数据填充表单,只需将数据传递给 $this->form->fill()
方法。比如,如果你在编辑已有的文章(post),你可以这样做:
use App\Models\Post;
public function mount(Post $post): void
{
$this->form->fill($post->toArray());
}
使用 $this->form->fill()
方法,而不是直接将数据赋值给 $this->data
属性。这是因为在存入数据库之前,文章的数据需要在内部转换成有用的格式。
设置表单模型
让 $form
访问模型有几个用处:
- 它允许表单中的字段从模型中加载信息。比如,Select 字段可以自动从数据库加载选项。
- 表单可以自动加载并保存模型的关联数据。比如,你有一个编辑文章(Post)的表单,使用 Repeater 管理与文章管理的评论。当调用
$this->form->fill([...])
时,Filament 会自动为那个 Post 加载评论,并且在调用$this->form->getState()
时,将其保存回关联之中。 - 像
exists()
和unique()
这样的验证规则,可以自动从模型中检索数据库表名。
如果存在模型,建议将其传递给表单。如前所述,它可以解锁 Filament 表单构造器的许多新能力。
使用 $form->model()
方法,可以将模型传递给表单:
use App\Models\Post;
use Filament\Forms\Form;
public Post $post;
public function form(Form $form): Form
{
return $form
->schema([
// ...
])
->statePath('data')
->model($this->post);
}
表单提交后传递表单模型
有些情况下,表单模型在表单提交之前是不可用的。比如,创建 Post 的表单中,表单提交之前 post 模型并不存在。因此,你不能将其传入到 $form->model()
。不过,你可以传递模型类替代:
use App\Models\Post;
use Filament\Forms\Form;
public function form(Form $form): Form
{
return $form
->schema([
// ...
])
->statePath('data')
->model(Post::class);
}
就其本身而言,这并不比传递模型实例更强大。比如,关联不会在创建之后保存到 post 中。为此,你需要在 post 创建之后,将其传递给表单,并调用 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()
传递给表单。请确保所有字段在类中都有他们自己的 public 属性。
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Form;
public ?string $title = null;
public ?string $content = null;
public function form(Form $form): Form
{
return $form
->schema([
TextInput::make('title')
->required(),
MarkdownEditor::make('content'),
// ...
]);
}
使用多个表单
默认情况下,InteractsWithForms
trait 每个 Livewire 组件只能处理一个表单 —— 即 form()
。要添加多个表单到 Livewire 组件,你可以在 getForms()
方法中定义,并返回包含每个表单名的数组:
protected function getForms(): array
{
return [
'editPostForm',
'createCommentForm',
];
}
现在,通过与上述表单名同名的方法,每个表单都能在 Livewire 组件中定义:
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Form;
public function editPostForm(Form $form): Form
{
return $form
->schema([
TextInput::make('title')
->required(),
MarkdownEditor::make('content'),
// ...
])
->statePath('postData')
->model($this->post);
}
public function createCommentForm(Form $form): Form
{
return $form
->schema([
TextInput::make('name')
->required(),
TextInput::make('email')
->email()
->required(),
MarkdownEditor::make('content')
->required(),
// ...
])
->statePath('commentData')
->model(Comment::class);
}
现在,每个表单都能通过表单名而非 form
定位。比如,你可以使用 $this->editPostForm->fill([...])
填充文章(Post)表单;或者可以使用 $this->createCommentForm->getState()
获取评论(Comment)表单的数据。
你可以注意到,每个表单都有其唯一的 statePath()
。每个表单都会在 Livewire 组件上将其状态(state)写入到不同数组中,因此,定义如下数组很重要:
public ?array $postData = [];
public ?array $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:livewire-form RegistrationForm
这将会生成新的 app/Livewire/RegistrationForm.php
组件,你可以对其进行自定义。
为 Eloquent 模型生成表单
Filament 也可以为指定的 Eloquent 模型生 成表单。这更为强大,因为它能自动为你保存表单数据,并确保表对单字段进行合理配置来访问该模型。
当使用 make:livewire-form
命令生成表单时,它会询问模型名称:
php artisan make:livewire-form Products/CreateProduct
为 Eloquent 记录生成编辑表单
默认情况下,传入模型到 make:livewire-form
会产生一个表单,用于在数据库中生成新记录。如果你传入 --edit
标志到该命令,它会为特定记录生成编辑表单。这回使用记录数据自动填充表单,并在提交后将数据保存回模型中。
php artisan make:livewire-form Products/EditProduct --edit
自动生成表单 Schema
Filament 可以基于模型数据库字段,猜测你想要在 Schema 中添加哪些表单字段。生成表单时,你可以使用 --generate
标志:
php artisan make:livewire-form Products/CreateProduct --generate
如果标中包含 ENUM 字段,
doctrine/dbal
将会无法扫描表并且崩溃。因此,如果包含 ENUM 字段,Filament 将无法生成 Schema。更多关于该问题的信息,请查阅此处。