Livewire Laravel

TinyMCE als Livewire Component

Chris
Geschäftsführer, PHP Senior-Entwickler
Aktualisiert:
TinyMce in a Livewire Component.

Laravel Livewire ist eine massive Arbeitserleichterung zur entwicklung dynamischer Webapps. Aber es hat seine Tücken. Wenn man es mit externen JavaScript-Bibliotheken wie TinyMCE kombinieren möchte, kann man auf unerwartete Probleme stoßen.

Das Problem
Laravel Livewire aktualisiert bei jedem Update das DOM-Element. Das bedeutet, dass, wenn man TinyMCE in einem Livewire-Component verwendet, die TinyMCE-Instanz bei jedem Livewire-Update zerstört und neu initialisiert wird. Das macht die flüssige Nutzung des Editors unmöglich.

Die Lösung
Glücklicherweise gibt es Wege, dieses Problem zu umgehen. Wir können wire:ignore verwenden, um zu verhindern, dass Livewire bestimmte DOM-Elemente verändert. Mittels Events steuern wir den Inhalt von TinyMCE um ihn zu speichern oder zu aktualisieren.

Es gibt eine gute Möglichkeit, dieses Problem zu lösen. Mit wire:ignore (Dokumentation zu wire:ignore) können wir Livewire daran zu hindern, bestimmte DOM-Elemente zu verändern. Mit Events steuern wir den Inhalt von TinyMCE, um ihn zu speichern oder zu aktualisieren.

<!-- Blade-Template mit JavaScript -->
<div>
    <script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script>
    <script>
        tinymce.init({
            selector: '#editor',
            forced_root_block: false,
            setup: function (editor) {
                editor.on('init change', function () {
                    editor.save();
                });
                editor.on('change', function (e) {
                    @this.set('document', editor.getContent());
                });
            }
        });
    </script>
    <div wire:ignore>
        <textarea id="editor" wire:model="document"></textarea>
    </div>
    <div>
        <button type="submit" wire:click="create">Speichern</button>
    </div>
    <div>
        @if (session()->has('message'))
            <div x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 3000)">
                {{ session('message') }}
            </div>
        @endif
    </div>
</div>Language:html