You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何扩展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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:44:57