在 Livewire 组件中渲染操作
WARNING
继续之前,请确认项目中已安装 filament/actions。可通过运行以下命令检查:
composer show filament/actions若尚未安装,请参阅安装指南,并按说明配置独立组件。
设置 Livewire 组件
首先,生成一个新的 Livewire 组件:
php artisan make:livewire ManagePost然后,在页面上渲染该 Livewire 组件:
@livewire('manage-post')或者,你也可以使用整页 Livewire 组件:
use App\Livewire\ManagePost;
use Illuminate\Support\Facades\Route;
Route::get('posts/{post}/manage', ManagePost::class);你必须在 Livewire 组件类上使用 InteractsWithActions 和 InteractsWithSchemas trait,并实现 HasActions 和 HasSchemas 接口:
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions;
use Filament\Schemas\Concerns\InteractsWithSchemas;
use Filament\Schemas\Concerns\RestrictsFileUploadsToSchemaComponents;
use Filament\Schemas\Contracts\HasSchemas;
use Livewire\Component;
class ManagePost extends Component implements HasActions, HasSchemas
{
use InteractsWithActions;
use InteractsWithSchemas;
use RestrictsFileUploadsToSchemaComponents;
// ...
}添加操作
添加一个返回操作的方法。方法名必须与操作名完全相同,或为操作名后接 Action:
use App\Models\Post;
use Filament\Actions\Action;
use Filament\Actions\Concerns\InteractsWithActions;
use Filament\Actions\Contracts\HasActions;
use Filament\Schemas\Concerns\InteractsWithSchemas;
use Filament\Schemas\Concerns\RestrictsFileUploadsToSchemaComponents;
use Filament\Schemas\Contracts\HasSchemas;
use Livewire\Component;
class ManagePost extends Component implements HasActions, HasSchemas
{
use InteractsWithActions;
use InteractsWithSchemas;
use RestrictsFileUploadsToSchemaComponents;
public Post $post;
public function deleteAction(): Action
{
return Action::make('delete')
->color('danger')
->requiresConfirmation()
->action(fn () => $this->post->delete());
}
// This method name also works, since the action name is `delete`:
// public function delete(): Action
// This method name does not work, since the action name is `delete`, not `deletePost`:
// public function deletePost(): Action
// ...
}最后,需要在视图中渲染该操作。为此,可使用 {{ $this->deleteAction }},并将 deleteAction 替换为你的操作方法名:
<div>
{{ $this->deleteAction }}
<x-filament-actions::modals />
</div>你还需要 <x-filament-actions::modals />,它会注入渲染操作模态框所需的 HTML。无论该组件有多少个操作,只需在 Livewire 组件中包含一次即可。
INFO
filament/actions 还包含以下包:
filament/formsfilament/infolistsfilament/notificationsfilament/support
这些包允许你在 Livewire 组件中使用它们的组件。 例如,若你的操作使用了 Notifications,请记得在布局中包含 @livewire('notifications'),并在 CSS 文件中添加 @import '../../vendor/filament/notifications/resources/css/index.css'。
若在操作中使用了其他 Filament 组件,请务必一并安装并集成对应的包。
传递操作参数
有时,你可能希望向操作传递参数。例如,若在同一视图中多次渲染同一操作,但每次针对不同模型,可将模型 ID 作为参数传入,之后再取回。为此,可在视图中调用该操作并以数组形式传入参数:
<div>
@foreach ($posts as $post)
<h2>{{ $post->title }}</h2>
{{ ($this->deleteAction)(['post' => $post->id]) }}
@endforeach
<x-filament-actions::modals />
</div>现在,你可以在操作方法中访问该帖子 ID:
use App\Models\Post;
use Filament\Actions\Action;
public function deleteAction(): Action
{
return Action::make('delete')
->color('danger')
->requiresConfirmation()
->action(function (array $arguments) {
$post = Post::find($arguments['post']);
$post?->delete();
});
}在 Livewire 视图中隐藏操作
若使用 hidden() 或 visible() 控制操作是否渲染,应用 @if 检查 isVisible() 来包裹该操作:
<div>
@if ($this->deleteAction->isVisible())
{{ $this->deleteAction }}
@endif
{{-- Or --}}
@if (($this->deleteAction)(['post' => $post->id])->isVisible())
{{ ($this->deleteAction)(['post' => $post->id]) }}
@endif
</div>hidden() 和 visible() 方法也会控制操作是否 disabled(),因此在用户无权限时仍可用于保护操作不被执行。将此逻辑封装在操作自身的 hidden() 或 visible() 中是良好实践,否则你需要在视图和 disabled() 中分别定义条件。
你还可以利用这一点,在操作隐藏时一并隐藏可能无需渲染的包裹元素:
<div>
@if ($this->deleteAction->isVisible())
<div>
{{ $this->deleteAction }}
</div>
@endif
</div>在 Livewire 视图中分组操作
你可以通过 <x-filament-actions::group> Blade 组件将操作分组到下拉菜单中,并将 actions 数组作为属性传入:
<div>
<x-filament-actions::group :actions="[
$this->editAction,
$this->viewAction,
$this->deleteAction,
]" />
<x-filament-actions::modals />
</div>你也可以传入任意属性来自定义触发按钮和下拉菜单的外观:
<div>
<x-filament-actions::group
:actions="[
$this->editAction,
$this->viewAction,
$this->deleteAction,
]"
label="Actions"
icon="heroicon-m-ellipsis-vertical"
color="primary"
size="md"
tooltip="More actions"
dropdown-placement="bottom-start"
/>
<x-filament-actions::modals />
</div>链式操作
你可以将多个操作串联起来:在当前操作完成后调用 replaceMountedAction() 方法,用另一个操作替换它:
use App\Models\Post;
use Filament\Actions\Action;
public function editAction(): Action
{
return Action::make('edit')
->schema([
// ...
])
// ...
->action(function (array $arguments) {
$post = Post::find($arguments['post']);
// ...
$this->replaceMountedAction('publish', $arguments);
});
}
public function publishAction(): Action
{
return Action::make('publish')
->requiresConfirmation()
// ...
->action(function (array $arguments) {
$post = Post::find($arguments['post']);
$post->publish();
});
}现在,提交第一个操作后,第二个操作会取而代之打开。原先传给第一个操作的参数会传给第二个操作,因此你可以用它们在请求之间持久化数据。
若取消第一个操作,第二个不会打开。若取消第二个操作,第一个已经执行,无法撤销。
以编程方式触发操作
有时你可能需要在用户未点击内置触发按钮的情况下触发操作,尤其是从 JavaScript 中。以下是一个可注册在 Livewire 组件上的示例操作:
use Filament\Actions\Action;
public function testAction(): Action
{
return Action::make('test')
->requiresConfirmation()
->action(function (array $arguments) {
dd('Test action called', $arguments);
});
}可在 HTML 中使用 wire:click 属性,通过调用 mountAction() 方法触发该操作,并可选择传入希望可用的任意参数:
<button wire:click="mountAction('test', { id: 12345 })">
Button
</button>要从 JavaScript 触发该操作,可使用 $wire 工具,并传入相同参数:
$wire.mountAction('test', { id: 12345 })