有没有正确的方法将 Trix 编辑器与 Livewire 连接起来?

Is there a proper way to wire up Trix editor with Livewire?

在将 Trix 编辑器内容与 Livewire 连接在一起时,我遇到了问题。我认为问题是当 Livewire 从 Trix 接收内容时,内容被换出并且 Trix 被禁用。有没有更好的方法?

我所做的工作如下。目前,该页面被重定向到自身以重新启动 Trix(击败了 Livewire 的全部要点,但它也被用于其他事情)。

<div>
  <input
      id="newCommentTextTrixContent"
      type="hidden"
      wire:model="newCommentText"
  >

  <trix-editor
      id="newCommentTextTrixEditor"
      input="newCommentTextTrixContent"
  ></trix-editor>


  <button wire:click="addComment(document.getElementById('newCommentTextTrixEditor').innerHTML)">Add Comment</button>
</div>

我试过了

我敢肯定像后者这样的东西更好,但是 Trix 每次都会以某种方式重新启动。这一切看起来有点混乱 - 所以问题是,正确的方法是什么?

我通过使用 Trix 的内置事件让它工作。

<input id="about" name="about" type="hidden" value="{{ $about }}">
<trix-editor input="about" class="wysiwyg-content"></trix-editor>

<script>
    var about = document.getElementById("about")

    addEventListener("trix-change", function(event) {
        console.log(about.getAttribute('value'));
        @this.set('about', about.getAttribute('value'))
    })
</script>

我成功了。使用最新的 Livewire 和 Alpine 安装,代码大致如下。

    <div wire:ignore>
        <trix-editor
            class="formatted-content"
            x-data
            x-on:trix-change="$dispatch('input', event.target.value)"
            x-ref="trix"
            wire:model.debounce.60s="newCommentText"
            wire:key="uniqueKey"
        ></trix-editor>
    </div>

为什么这样做有效?

  • 您需要在父节点上 wire:ignore,因为 Trix 将工具栏插入到文本区域上方。 wire:ignore 阻止 Livewire 担心它,因此不会在下一个周期中删除它或弄乱它。
  • 您需要一个 wire:key,因为 DOM 会稍微移动,这有助于 Livewire 跟踪它。
  • 我建议使用长去抖动,这是一种 hack,因为 .lazy 修饰符不适用于文本。此外,每次按键时等待 Ajax 是痛苦的。
  • alpine 事件确保 Trix 事件(如粗体、斜体等)仍然被触发

就是这样。我在上面使用它在评论流的末尾重复提交评论,一切似乎都正常。祝你好运!

请注意,我也有类似的 CKEditor,如所述here

作为@Kurucu 的回答的扩展,以及来自@Rehan 的评论;

This seems to work very well. But when I apply styles like li or bold it doesnt retain in the wire:model. Ex: <div>foo<br>bar<br>foobar</div> I applied the Bullets here the tags are missing. Did you face this issue? – Rehan

要解决按下粗体、斜体或引号按钮时没有更新值的问题,请将以下部分添加到 trix 编辑器(注意 x-on:trix-change="$dispatch('input', event.target.value)"):

<div wire:ignore>
    <trix-editor
        class="formatted-content"
        x-data
        x-on:trix-change="$dispatch('input', event.target.value)"
        wire:model.debounce.1000ms="newCommentText"
        wire:key="uniqueKey"
    ></trix-editor>
</div>

上面的选项有效,但没有从我的字段中取回数据,这是对我有用的方法,使用 AlpineJS 的 @entangle 进行了一些微调。 以下是我的工作解决方案:

<div class="mb-2" x-data="{ description: @entangle('description').defer }"

             x-init="$watch('description', function (value) {
                        $refs.trix.editor.loadHTML(value)
                        var length = $refs.trix.editor.getDocument().toString().length
                        $refs.trix.editor.setSelectedRange(length - 1)
                        }
                    )" wire:ignore>

            <label class="form-label">Job Description <span class="text-danger">*</span></label>
            @error('description')
            <span class="error d-inline-block"><i class="mdi mdi-alert-circle"> </i> {{$message}}</span>
            @enderror
            <input name="description" id="description" type="hidden" x-model="description">
            <div x-on:trix-change.debounce.1000ms="description = $refs.trix.value">
                <trix-editor x-ref="trix" input="description" class="overflow-y-scroll"
                             style="height: 20rem;"></trix-editor>
            </div>
        </div>