如何扩展Filament PHP富编辑器组件并添加自定义API数据更新按钮
扩展Filament富编辑器:添加自定义按钮并更新内容
我正在扩展Filament表单的富编辑器组件,目标是添加一个自定义按钮,点击后通过API获取数据并更新编辑器内容。已在vendor/filament/forms/resources/views/components/rich-editor.blade.php中添加按钮,但调用setState()无法更新编辑器内容,需要解决数据获取后的内容同步问题。
当前实现代码
1. 自定义工具栏按钮(rich-editor.blade.php)
@if ($hasToolbarButton(['noteOption'])) <button wire:click="dispatchFormEvent('init::cnotes', '{{ $getStatePath() }}', '{{ $getId() }}')"> Get Latest Notes </button> @endif
2. 富编辑器组件扩展代码
class RichEditor extends Field implements Contracts\CanBeLengthConstrained, Contracts\HasFileAttachments { // ... protected array | Closure $toolbarButtons = [ 'attachFiles', 'blockquote', 'bold', 'bulletList', 'codeBlock', 'h2', 'h3', 'italic', 'link', 'orderedList', 'redo', 'strike', 'undo', 'cnotes' ]; protected function setUp(): void { parent::setUp(); $this->registerListeners([ 'init::cnotes' => [ function ($component, string $statePath, string $uuid): void { if ($component->isDisabled()) { return; } if ($statePath !== $component->getStatePath()) { return; } // 已能获取编辑器当前值 dump($component->getState()); // 获取最新企业信息文本 $notes = $this->fetchCompanyNotes(); // 尝试更新编辑器,但此代码无效 $component->setState($notes); }, ], ]); } }
问题核心
仅调用$component->setState($notes)只能更新组件后端状态,无法同步到前端的Tiptap编辑器实例(Filament富编辑器底层基于Tiptap)。
解决方案
1. 修改组件事件监听器,触发前端更新事件
在init::cnotes回调中,除了更新后端state,还要发送浏览器事件通知前端编辑器:
protected function setUp(): void { parent::setUp(); $this->registerListeners([ 'init::cnotes' => [ function ($component, string $statePath, string $uuid): void { if ($component->isDisabled()) { return; } if ($statePath !== $component->getStatePath()) { return; } $notes = $this->fetchCompanyNotes(); // 1. 更新组件后端状态 $component->setState($notes); // 2. 触发前端事件,传递编辑器ID和新内容 $component->dispatchBrowserEvent('update-rich-editor-content', [ 'editorId' => $uuid, 'content' => $notes, ]); }, ], ]); }
2. 在Blade视图中添加JS监听事件,同步编辑器内容
在rich-editor.blade.php末尾添加以下脚本,监听浏览器事件并调用Tiptap API更新内容:
<script> document.addEventListener('livewire:initialized', function () { window.addEventListener('update-rich-editor-content', function (event) { const { editorId, content } = event.detail; // Filament将富编辑器实例存储在window.filamentRichEditors对象中,以UUID为键 const editor = window.filamentRichEditors[editorId]; if (editor) { // 替换编辑器全部内容 editor.commands.setContent(content, { replace: true }); } }); }); </script>
3. 额外注意事项
- 避免直接修改
vendor目录文件:后续Filament版本更新会覆盖修改,正确做法是创建自定义富编辑器组件继承Filament的RichEditor,并发布视图进行自定义修改。 - 异步数据处理:如果
fetchCompanyNotes()是异步API调用,需用wire:click.prevent并处理异步逻辑,确保数据返回后再执行更新操作。
内容的提问来源于stack exchange,提问作者Ask17
相关产品推荐
相关产品推荐

