表单构造器
在 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接口并使用InteractsWithFormstrait。
- 定义公共 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->attributesToArray());}使用 $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 --generateEdit on GitHub如果标中包含 ENUM 字段,
doctrine/dbal将会无法扫描表并且崩溃。因此,如果包含 ENUM 字段,Filament 将无法生成 Schema。更多关于该问题的信息,请查阅此处。
Still need help? Join our Discord community or open a GitHub discussion